@oracle-agent/oracle 0.28.25 → 0.28.27
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/assets/skills/oracle-chain-graphs-telegram-cards/SKILL.md +10 -1
- package/dist/assets/skills/oracle-desk-product/SKILL.md +1 -1
- package/dist/bin/oracle-gateway.mjs +32 -27
- package/dist/bin/oracle-mev-arb-shadow.mjs +7 -0
- package/dist/bin/oracle-mev-control.mjs +9 -0
- package/dist/bin/oracle-mev-keygen.mjs +5 -0
- package/dist/bin/oracle-mev-operator.mjs +14 -0
- package/dist/bin/oracle-mev-restore-apply.mjs +10 -0
- package/dist/bin/oracle-mev-restore-approve.mjs +5 -0
- package/dist/bin/oracle-mev-restore-keygen.mjs +5 -0
- package/dist/bin/oracle-mev-shadow.mjs +7 -0
- package/dist/bin/oracle.mjs +11 -8
- package/dist/cli/commands/chat.mjs +159 -159
- package/dist/cli/commands/doctor.mjs +3 -3
- package/dist/cli/commands/eval.mjs +43 -43
- package/dist/cli/commands/mev.mjs +35 -0
- package/dist/cli/commands/model.mjs +162 -162
- package/dist/cli/commands/receipt.mjs +2 -2
- package/dist/cli/commands/sign.mjs +8 -8
- package/dist/cli/commands/signer.mjs +13 -13
- package/dist/cli/commands/swap.mjs +27 -18
- package/dist/cli/commands/venues.mjs +2 -2
- package/dist/local-signer/anvil-attestation-worker.mjs +1 -1
- package/dist/local-signer/index.mjs +3 -3
- package/dist/local-signer/runtime.mjs +10 -10
- package/package.json +10 -2
|
@@ -20,6 +20,8 @@ cards.
|
|
|
20
20
|
held-position context when API keys/account reads are configured.
|
|
21
21
|
- Polymarket cards: event, market, Yes/No prices, volume, BBO, resolution-risk
|
|
22
22
|
notes, and prepared order intent only when user auth/API keys are configured.
|
|
23
|
+
- Swap cards: best same-chain swap (net of gas/fees) plus optional best bridge,
|
|
24
|
+
runners-up, and Refresh quote. Prepare/Execute buttons only with a local grant.
|
|
23
25
|
|
|
24
26
|
## Data rules
|
|
25
27
|
|
|
@@ -36,7 +38,14 @@ cards.
|
|
|
36
38
|
- Avoid markdown traps: no unescaped underscore labels, avoid repeated `$` spans.
|
|
37
39
|
- Keep full contracts/mints visible; never truncate the only identifier.
|
|
38
40
|
- Chart rendering must soft-fail: card still sends if the image fails.
|
|
39
|
-
- No buy/sell buttons unless the recipient has a valid local grant/session.
|
|
41
|
+
- No buy/sell/prepare/execute buttons unless the recipient has a valid local grant/session.
|
|
42
|
+
- A swap card may quote for anyone. It must not imply a fill. Execute still
|
|
43
|
+
prepares an unsigned artifact for the local signer / owner wallet.
|
|
44
|
+
- Approve cards (Photon-style Allow/Deny) are Telegram-first. They appear when
|
|
45
|
+
the local signer is running and a pending artifact exists.
|
|
46
|
+
- `/approve` / `/deny` are owner-only fallbacks for WhatsApp, Discord, Signal,
|
|
47
|
+
and any chat that cannot render inline buttons. Do not prefer them on Telegram
|
|
48
|
+
when the card is available.
|
|
40
49
|
|
|
41
50
|
## Graph schema
|
|
42
51
|
|
|
@@ -97,7 +97,7 @@ does not prove npm users receive it. A locally hosted model/data/policy loop doe
|
|
|
97
97
|
a bundled signer. A merged feature is not public until the npm artifact containing it is
|
|
98
98
|
published and inspected.
|
|
99
99
|
|
|
100
|
-
**Candidate release in this source tree:** public package `@oracle-agent/oracle@0.28.
|
|
100
|
+
**Candidate release in this source tree:** public package `@oracle-agent/oracle@0.28.27`
|
|
101
101
|
ships the encrypted local vault + short-lived loopback signer. Hosted/keyless
|
|
102
102
|
Oracle cannot hold keys or move funds. Self-host after `oracle sign init|import` is **auto-armed**
|
|
103
103
|
for user-initiated actions. Public still charges the disclosed fee card; Administrator
|
|
@@ -1,32 +1,37 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var Re=Object.defineProperty;var p=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(a){throw r=[a],a}};var w=(e,t)=>{for(var r in t)Re(e,r,{get:t[r],enumerable:!0})};var G={};w(G,{A2ABus:()=>j,normalizeName:()=>C});function C(e){return String(e||"").trim().toLowerCase().replace(/^@/,"")}var j,H=p(()=>{j=class{constructor({maxHops:t=4,historyCap:r=200}={}){this.maxHops=t,this.historyCap=r,this.agents=new Map,this.history=[],this.seq=0}register(t,{role:r="",chains:a=[],handler:o}={}){let n=C(t);if(!n)throw new Error("a2a: agent name required");if(this.agents.has(n))throw new Error(`a2a: agent '${n}' already registered`);if(typeof o!="function")throw new Error(`a2a: agent '${n}' needs a handler`);return this.agents.set(n,{name:n,role:String(r),chains:a.map(String),handler:o}),this.agents.get(n)}unregister(t){this.agents.delete(C(t))}roster(){return[...this.agents.values()].map(({name:t,role:r,chains:a})=>({name:t,role:r,chains:a}))}async send({from:t,to:r,text:a,kind:o="consult",hops:n=0}={}){let i=C(t),s=C(r);if(!i||!this.agents.has(i))return{ok:!1,error:`a2a: unknown sender '${t}'`};if(!s||!this.agents.has(s))return{ok:!1,error:`a2a: unknown recipient '${r}' (roster: ${[...this.agents.keys()].join(", ")||"empty"})`};if(s===i)return{ok:!1,error:"a2a: self-send refused"};let c=String(a||"").trim().slice(0,8e3);if(!c)return{ok:!1,error:"a2a: empty message"};let l=Number(n)+1;if(l>this.maxHops)return this.record({from:i,to:s,kind:o,dropped:"hop-limit"}),{ok:!1,error:`a2a: hop limit ${this.maxHops} reached \u2014 dropped`};let u={id:`a2a-${Date.now()}-${++this.seq}`,from:i,to:s,kind:String(o),text:c,hops:l,ts:new Date().toISOString()};this.record(u);try{let d=await this.agents.get(s).handler(u);return d&&this.record({id:`${u.id}-reply`,from:s,to:i,kind:"reply",text:String(d).slice(0,8e3),hops:l,ts:new Date().toISOString()}),{ok:!0,reply:d||null,id:u.id}}catch(d){return{ok:!1,error:`a2a: '${s}' handler failed: ${d.message}`}}}record(t){this.history.push(t),this.history.length>this.historyCap&&this.history.splice(0,this.history.length-this.historyCap)}recent(t=20){return this.history.slice(-t)}}});import v from"node:fs";import Le from"node:os";import _ from"node:path";import{fileURLToPath as ve}from"node:url";function B(){return process.env.ORACLE_FAKE_HOME||Le.homedir()}function Te(){return process.env.ORACLE_PUBLIC_DESKTOP==="1"}function P(){return Te()?process.env.ORACLE_CONFIG_DIR||_.join(B(),".config","oracle"):_.join(B(),".config","oracle")}function Ue(){return _.join(P(),"desk.json")}function je(){return _.join(P(),"env")}function y({force:e=!1}={}){if(y._done&&!e)return y._result||null;y._done=!0;let t={},r=(o,n)=>{if(n==null)return;let i=String(n).trim();i&&(process.env[o]!=null&&String(process.env[o]).trim()!==""||(process.env[o]=i,t[o]=i))};try{let o=je();if(v.existsSync(o))for(let n of v.readFileSync(o,"utf8").split(/\r?\n/)){let i=n.match(/^\s*([A-Z0-9_]+)\s*=\s*(.*?)\s*$/);if(!i||i[2].startsWith("#"))continue;let s=i[2];(s.startsWith('"')&&s.endsWith('"')||s.startsWith("'")&&s.endsWith("'"))&&(s=s.slice(1,-1)),r(i[1],s)}}catch{}try{let o=Ue();if(v.existsSync(o)){let n=JSON.parse(v.readFileSync(o,"utf8"));n&&typeof n=="object"&&(r("ORACLE_DESK_URL",n.deskUrl||n.dataUrl||n.url),r("ORACLE_DATA_URL",n.dataUrl||n.deskUrl||n.url),r("ORACLE_API_URL",n.apiUrl||n.dataUrl||n.deskUrl),r("ORACLE_PUBLIC_URL",n.publicUrl||n.deskUrl||n.dataUrl),r("ORACLE_EXEC_URL",n.execUrl),r("MAD_DESK_URL",n.deskUrl||n.dataUrl))}}catch{}let a=process.env.ORACLE_DESK_URL||process.env.ORACLE_DATA_URL||"";return a&&(r("ORACLE_DESK_URL",a),r("ORACLE_DATA_URL",a),r("ORACLE_API_URL",a),r("ORACLE_PUBLIC_URL",a),r("MAD_DESK_URL",a)),y._result=Object.keys(t).length?t:null,y._result}var Pe,Nr,z=p(()=>{Pe=_.dirname(ve(import.meta.url)),Nr=_.resolve(Pe,"../..");try{y()}catch{}});function T(e){return String(e||"").trim()||void 0}function Ne(e,{required:t=!1}={}){let r=T(e)?.toLowerCase();if(!r){if(t)throw new Error("model provider is required");return}if(!De.has(r))throw new Error(`unsupported provider: ${r}`);return r}function Ie(e,{required:t=!1}={}){let r=T(e);if(!r){if(t)throw new Error("model is required");return}if(r.includes("..")||r.startsWith("/")||!/^[a-zA-Z0-9._:/-]{1,200}$/.test(r))throw new Error("invalid model id");return r}function Me(e){let t=T(e);if(!t||t.length>2048)throw new Error("invalid custom base URL");let r;try{r=new URL(t)}catch{throw new Error("invalid custom base URL")}let a=r.hostname.toLowerCase().replace(/^\[|\]$/g,""),o=a==="localhost"||a==="127.0.0.1"||a==="::1";if(r.protocol!=="https:"&&!(r.protocol==="http:"&&o)||r.username||r.password||r.search||r.hash)throw new Error("custom base URL must use HTTPS or loopback HTTP without credentials, query, or fragment");return r.toString().replace(/\/+$/,"")}function W({provider:e,model:t,baseUrl:r}={},{requireModel:a=!1}={}){let o=Ne(e),n=Ie(t,{required:a});if(o==="custom")return{provider:o,...n?{model:n}:{},baseUrl:Me(r)};if(T(r))throw new Error("baseUrl is only supported for the custom provider");return{...o?{provider:o}:{},...n?{model:n}:{}}}var De,K=p(()=>{De=new Set(["openrouter","openai","anthropic","xai","deepseek","gemini","kimi","mistral","nous","custom","anthropic-oauth","openai-codex","xai-oauth"])});import J from"node:fs";import Fe from"node:path";function He(){return Fe.join(P(),"model.json")}function k(e){return String(e||"").trim()||void 0}function Be(e={}){let t=k(e.backend)?.toLowerCase()||"auto",r=W({provider:e.provider,model:e.model,baseUrl:e.baseUrl},{requireModel:t==="standalone"}),a=k(e.apiKeyEnv),o=Number.parseInt(String(e.contextLength||""),10),n=k(e.reasoningEffort),i=k(e.computeHost||e.remoteHost),s=k(e.computeUser||e.remoteUser),c=k(e.computePath||e.remotePath);if(!Ge.has(t))throw new Error(`unsupported backend: ${t}`);if(process.env.ORACLE_PUBLIC_DESKTOP==="1"&&["remote","arch"].includes(t))throw new Error("remote compute backends are disabled in the public desktop");if(a&&!/^[A-Z][A-Z0-9_]*$/.test(a))throw new Error("api key env must be an uppercase environment variable name");if(t==="remote"&&!i)throw new Error("remote backend requires computeHost");return{backend:t,...r,...a?{apiKeyEnv:a}:{},...Number.isFinite(o)&&o>0?{contextLength:o}:{},...n?{reasoningEffort:n}:{},...i?{computeHost:i}:{},...s?{computeUser:s}:{},...c?{computePath:c}:{}}}function X(){let e=He();if(!J.existsSync(e))return null;try{return Be(JSON.parse(J.readFileSync(e,"utf8")))}catch{return null}}var Ge,Y=p(()=>{z();K();Ge=new Set(["auto","standalone","hermes","remote","arch"])});import{execFile as ze}from"node:child_process";import{existsSync as We,mkdirSync as Ke,readFileSync as q,realpathSync as Je,writeFileSync as Xe}from"node:fs";import m from"node:path";import{promisify as Ye}from"node:util";import{fileURLToPath as V}from"node:url";function Qe(e=import.meta.url){try{let t=Je(V(e)),r=`${m.sep}node_modules${m.sep}`,a=t.lastIndexOf(r);if(a>0)return{root:t.slice(0,a),managed:!0}}catch{}return{root:null,managed:!1}}function N(e=import.meta.url){try{let t=m.dirname(V(e));for(let r=0;r<8;r+=1){let a=m.join(t,"package.json");if(We(a)){let n=JSON.parse(q(a,"utf8"));if(n?.name===D&&n.version)return n.version}let o=m.dirname(t);if(o===t)break;t=o}}catch{return null}return null}function er(e,t){let r=n=>String(n).replace(/^v/,"").split("-")[0].split(".").map(i=>Number.parseInt(i,10)||0),a=r(e),o=r(t);for(let n=0;n<Math.max(a.length,o.length);n+=1){let i=a[n]??0,s=o[n]??0;if(i>s)return 1;if(i<s)return-1}return 0}function Z(e){let t=e?.stateDir||m.join(process.env.HOME||".",".oracle");return m.join(t,"update-check.json")}function rr(e){try{return JSON.parse(q(Z(e),"utf8"))}catch{return null}}function tr(e,t){try{let r=Z(e);Ke(m.dirname(r),{recursive:!0}),Xe(r,`${JSON.stringify(t,null,2)}
|
|
3
|
-
`)}
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
`)
|
|
7
|
-
`),
|
|
8
|
-
`)
|
|
9
|
-
${
|
|
10
|
-
`)}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
`),
|
|
14
|
-
|
|
2
|
+
var tr=Object.defineProperty;var l=(t,e,r)=>()=>{if(r)throw r[0];try{return t&&(e=t(t=0)),e}catch(n){throw r=[n],n}};var L=(t,e)=>{for(var r in e)tr(t,r,{get:e[r],enumerable:!0})};var Re={};L(Re,{A2ABus:()=>re,normalizeName:()=>W});function W(t){return String(t||"").trim().toLowerCase().replace(/^@/,"")}var re,Pe=l(()=>{re=class{constructor({maxHops:e=4,historyCap:r=200}={}){this.maxHops=e,this.historyCap=r,this.agents=new Map,this.history=[],this.seq=0}register(e,{role:r="",chains:n=[],handler:o}={}){let i=W(e);if(!i)throw new Error("a2a: agent name required");if(this.agents.has(i))throw new Error(`a2a: agent '${i}' already registered`);if(typeof o!="function")throw new Error(`a2a: agent '${i}' needs a handler`);return this.agents.set(i,{name:i,role:String(r),chains:n.map(String),handler:o}),this.agents.get(i)}unregister(e){this.agents.delete(W(e))}roster(){return[...this.agents.values()].map(({name:e,role:r,chains:n})=>({name:e,role:r,chains:n}))}async send({from:e,to:r,text:n,kind:o="consult",hops:i=0}={}){let s=W(e),a=W(r);if(!s||!this.agents.has(s))return{ok:!1,error:`a2a: unknown sender '${e}'`};if(!a||!this.agents.has(a))return{ok:!1,error:`a2a: unknown recipient '${r}' (roster: ${[...this.agents.keys()].join(", ")||"empty"})`};if(a===s)return{ok:!1,error:"a2a: self-send refused"};let u=String(n||"").trim().slice(0,8e3);if(!u)return{ok:!1,error:"a2a: empty message"};let d=Number(i)+1;if(d>this.maxHops)return this.record({from:s,to:a,kind:o,dropped:"hop-limit"}),{ok:!1,error:`a2a: hop limit ${this.maxHops} reached \u2014 dropped`};let f={id:`a2a-${Date.now()}-${++this.seq}`,from:s,to:a,kind:String(o),text:u,hops:d,ts:new Date().toISOString()};this.record(f);try{let m=await this.agents.get(a).handler(f);return m&&this.record({id:`${f.id}-reply`,from:a,to:s,kind:"reply",text:String(m).slice(0,8e3),hops:d,ts:new Date().toISOString()}),{ok:!0,reply:m||null,id:f.id}}catch(m){return{ok:!1,error:`a2a: '${a}' handler failed: ${m.message}`}}}record(e){this.history.push(e),this.history.length>this.historyCap&&this.history.splice(0,this.history.length-this.historyCap)}recent(e=20){return this.history.slice(-e)}}});import z from"node:fs";import rr from"node:os";import R from"node:path";import{fileURLToPath as nr}from"node:url";function Be(){return process.env.ORACLE_FAKE_HOME||rr.homedir()}function ir(){return process.env.ORACLE_PUBLIC_DESKTOP==="1"}function P(){return ir()?process.env.ORACLE_CONFIG_DIR||R.join(Be(),".config","oracle"):R.join(Be(),".config","oracle")}function ar(){return R.join(P(),"desk.json")}function sr(){return R.join(P(),"env")}function _({force:t=!1}={}){if(_._done&&!t)return _._result||null;_._done=!0;let e={},r=(o,i)=>{if(i==null)return;let s=String(i).trim();s&&(process.env[o]!=null&&String(process.env[o]).trim()!==""||(process.env[o]=s,e[o]=s))};try{let o=sr();if(z.existsSync(o))for(let i of z.readFileSync(o,"utf8").split(/\r?\n/)){let s=i.match(/^\s*([A-Z0-9_]+)\s*=\s*(.*?)\s*$/);if(!s||s[2].startsWith("#"))continue;let a=s[2];(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),r(s[1],a)}}catch{}try{let o=ar();if(z.existsSync(o)){let i=JSON.parse(z.readFileSync(o,"utf8"));i&&typeof i=="object"&&(r("ORACLE_DESK_URL",i.deskUrl||i.dataUrl||i.url),r("ORACLE_DATA_URL",i.dataUrl||i.deskUrl||i.url),r("ORACLE_API_URL",i.apiUrl||i.dataUrl||i.deskUrl),r("ORACLE_PUBLIC_URL",i.publicUrl||i.deskUrl||i.dataUrl),r("ORACLE_EXEC_URL",i.execUrl),r("MAD_DESK_URL",i.deskUrl||i.dataUrl))}}catch{}let n=process.env.ORACLE_DESK_URL||process.env.ORACLE_DATA_URL||"";return n&&(r("ORACLE_DESK_URL",n),r("ORACLE_DATA_URL",n),r("ORACLE_API_URL",n),r("ORACLE_PUBLIC_URL",n),r("MAD_DESK_URL",n)),_._result=Object.keys(e).length?e:null,_._result}var or,ro,ne=l(()=>{or=R.dirname(nr(import.meta.url)),ro=R.resolve(or,"../..");try{_()}catch{}});function V(t){return String(t||"").trim()||void 0}function ur(t,{required:e=!1}={}){let r=V(t)?.toLowerCase();if(!r){if(e)throw new Error("model provider is required");return}if(!cr.has(r))throw new Error(`unsupported provider: ${r}`);return r}function lr(t,{required:e=!1}={}){let r=V(t);if(!r){if(e)throw new Error("model is required");return}if(r.includes("..")||r.startsWith("/")||!/^[a-zA-Z0-9._:/-]{1,200}$/.test(r))throw new Error("invalid model id");return r}function dr(t){let e=V(t);if(!e||e.length>2048)throw new Error("invalid custom base URL");let r;try{r=new URL(e)}catch{throw new Error("invalid custom base URL")}let n=r.hostname.toLowerCase().replace(/^\[|\]$/g,""),o=n==="localhost"||n==="127.0.0.1"||n==="::1";if(r.protocol!=="https:"&&!(r.protocol==="http:"&&o)||r.username||r.password||r.search||r.hash)throw new Error("custom base URL must use HTTPS or loopback HTTP without credentials, query, or fragment");return r.toString().replace(/\/+$/,"")}function Fe({provider:t,model:e,baseUrl:r}={},{requireModel:n=!1}={}){let o=ur(t),i=lr(e,{required:n});if(o==="custom")return{provider:o,...i?{model:i}:{},baseUrl:dr(r)};if(V(r))throw new Error("baseUrl is only supported for the custom provider");return{...o?{provider:o}:{},...i?{model:i}:{}}}var cr,Me=l(()=>{cr=new Set(["openrouter","openai","anthropic","xai","deepseek","gemini","kimi","mistral","nous","custom","anthropic-oauth","openai-codex","xai-oauth"])});import qe from"node:fs";import fr from"node:path";function mr(){return fr.join(P(),"model.json")}function B(t){return String(t||"").trim()||void 0}function hr(t={}){let e=B(t.backend)?.toLowerCase()||"auto",r=Fe({provider:t.provider,model:t.model,baseUrl:t.baseUrl},{requireModel:e==="standalone"}),n=B(t.apiKeyEnv),o=Number.parseInt(String(t.contextLength||""),10),i=B(t.reasoningEffort),s=B(t.computeHost||t.remoteHost),a=B(t.computeUser||t.remoteUser),u=B(t.computePath||t.remotePath);if(!pr.has(e))throw new Error(`unsupported backend: ${e}`);if(process.env.ORACLE_PUBLIC_DESKTOP==="1"&&["remote","arch"].includes(e))throw new Error("remote compute backends are disabled in the public desktop");if(n&&!/^[A-Z][A-Z0-9_]*$/.test(n))throw new Error("api key env must be an uppercase environment variable name");if(e==="remote"&&!s)throw new Error("remote backend requires computeHost");return{backend:e,...r,...n?{apiKeyEnv:n}:{},...Number.isFinite(o)&&o>0?{contextLength:o}:{},...i?{reasoningEffort:i}:{},...s?{computeHost:s}:{},...a?{computeUser:a}:{},...u?{computePath:u}:{}}}function De(){let t=mr();if(!qe.existsSync(t))return null;try{return hr(JSON.parse(qe.readFileSync(t,"utf8")))}catch{return null}}var pr,Ue=l(()=>{ne();Me();pr=new Set(["auto","standalone","hermes","remote","arch"])});var je=l(()=>{});var H=l(()=>{});var F=l(()=>{});var ie=l(()=>{H();F()});import{isAddress as bo}from"ethers";var ae=l(()=>{ie();H();F()});import{Interface as yr,isAddress as ko}from"ethers";var No,We=l(()=>{ae();H();F();No=new yr(["function approve(address spender,uint256 amount) returns (bool)"])});import{Interface as br,isAddress as Lo}from"ethers";var Bo,Fo,He=l(()=>{ae();H();F();Bo=new br(["function approve(address spender,uint256 amount) returns (bool)"]),Fo=Object.freeze({42161:"0x1c3fa76e6e1088bce750f23a5bfcffa1efef6a41",43114:"0x8f550e53dfe96c055d5bdb267c21f268fcaf63b2"})});var N=l(()=>{});import{Interface as Er,MaxUint256 as Ho,isAddress as Jo,keccak256 as Go,toUtf8Bytes as zo}from"ethers";var Zo,J=l(()=>{je();We();He();N();F();Zo=new Er(["function approve(address spender,uint256 amount) returns (bool)"])});var ti,ri,Je=l(()=>{ti=300*1e3,ri=(()=>{let t=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(t)&&t>0?t:1800*1e3})()});var Y=l(()=>{J()});import{Address as si,NETWORK as ci,OutScript as ui,RawTx as li,SigHash as di,TEST_NETWORK as fi,Transaction as pi}from"@scure/btc-signer";var ue=l(()=>{});import{createHash as Sr}from"node:crypto";import{base58 as gi}from"@scure/base";import{getCompiledTransactionMessageDecoder as bi}from"@solana/transaction-messages";var Ge,Ei,le=l(()=>{Ge=t=>Sr("sha256").update(`global:${t}`).digest().subarray(0,8).toString("hex"),Ei=new Map([[Ge("route"),{name:"route",prefixBytes:0}],[Ge("shared_accounts_route"),{name:"shared_accounts_route",prefixBytes:1}]])});var ze=l(()=>{});var Oi,Ve=l(()=>{ze();Oi=64*1024});var Ke=l(()=>{Ve()});var Ye=l(()=>{Ke()});var Di,Ui,fe=l(()=>{N();Ye();Di=Object.freeze({"perp-order":"order","hip3-order":"order","hip4-order":"order","perp-bracket":"order","perp-cancel":"cancel","perp-leverage":"leverage","perp-isolated-margin":"margin","builder-fee-approval":"approveBuilder","hype-stake-deposit":"stake","hype-stake-withdraw":"unstake","hype-delegate":"delegate","hype-undelegate":"delegate"}),Ui=Object.freeze({"perp-order":"order","hip3-order":"order","hip4-order":"order","perp-bracket":"order","perp-cancel":"cancel","perp-leverage":"updateLeverage","perp-isolated-margin":"updateIsolatedMargin","builder-fee-approval":"approveBuilderFee","hype-stake-deposit":"cDeposit","hype-stake-withdraw":"cWithdraw","hype-delegate":"tokenDelegate","hype-undelegate":"tokenDelegate"})});var Hi,pe=l(()=>{N();Hi="0x"+"00".repeat(32)});var Ar,Ki,me=l(()=>{pe();N();Ar=Object.freeze([["salt","uint256"],["maker","address"],["signer","address"],["tokenId","uint256"],["makerAmount","uint256"],["takerAmount","uint256"],["side","uint8"],["signatureType","uint8"],["timestamp","uint256"],["metadata","bytes32"],["builder","bytes32"]]),Ki=Object.freeze(Ar.map(t=>t[0]))});var X=l(()=>{N()});import{Interface as tt}from"ethers";var Or,pa,Nr,ma,ha,wa,ga,Cr,ya,Q=l(()=>{J();ie();Je();Y();ue();le();fe();me();X();Or=new Set(["evm","evm-swap","evm-bridge","evm-nft","btc","sol","hl","poly","lighter"]),pa=Object.freeze({swap:5,bridge:5,perps:0,nft:0,mint:0,transfer:0,approve:0,order:0,cancel:0,leverage:0,margin:0,approveBuilder:0,stake:0,unstake:0,delegate:0}),Nr=Object.freeze({"0x04e45aaf":{provider:"uniswap-v3",action:"swap",layout:"router02-exact-input-single"},"0x414bf389":{provider:"uniswap-v3",action:"swap",layout:"swap-router-exact-input-single"},"0xc04b8d59":{provider:"uniswap-v3",action:"swap",layout:"exact-input-deadline"},"0xb858183f":{provider:"uniswap-v3",action:"swap",layout:"exact-input"},"0x5ae401dc":{provider:"uniswap-v3",action:"swap",layout:"multicall-deadline"},"0xa026383e":{provider:"aerodrome",action:"swap",layout:"aerodrome-exact-input-single"},"0x7b939232":{provider:"across-v3",action:"bridge",layout:"across-deposit-v3"}}),ma=Object.freeze({"0x161ac21f":{provider:"opensea-nft",action:"mint",layout:"seadrop-mint-public"},"0xc2f6663a":{provider:"opensea-nft",action:"mint",layout:"seadrop-mint-allowlist"}}),ha=new tt(["function buySpecificNFT(uint256 tokenId,uint256 maxCost) payable","function sellNFT(uint256 tokenId,uint256 minPayout) payable"]),wa=new tt(["function mintAllowList(address nftContract,address feeRecipient,address minterIfNotPayer,uint256 quantity,(uint80 mintPrice,uint48 maxTotalMintableByWallet,uint48 startTime,uint48 endTime,uint48 dropStageIndex,uint32 maxTokenSupplyForStage,uint16 feeBps,bool restrictFeeRecipients) mintParams,bytes32[] proof) payable"]),ga=Object.freeze({"0xa0712d68":{provider:"nft-mint",action:"mint",layout:"mint-quantity"},"0x1249c58b":{provider:"nft-mint",action:"mint",layout:"mint-no-args"},"0x2db11544":{provider:"nft-mint",action:"mint",layout:"mint-quantity"},"0xefef39a1":{provider:"nft-mint",action:"mint",layout:"mint-quantity"},"0xa6f2ae3a":{provider:"nft-mint",action:"mint",layout:"mint-no-args"}}),Cr=Object.freeze([...Or]),ya=Object.freeze({...Nr})});import{encode as xa}from"@msgpack/msgpack";import{keccak256 as Aa,verifyTypedData as va}from"ethers";var ka,Ia,he=l(()=>{ka=Object.freeze({name:"Exchange",version:"1",chainId:1337,verifyingContract:"0x0000000000000000000000000000000000000000"}),Ia=Object.freeze({Agent:[{name:"source",type:"string"},{name:"connectionId",type:"bytes32"}]})});var we=l(()=>{X()});import{ed25519 as Ra}from"@noble/curves/ed25519.js";import{base58 as Ba}from"@scure/base";import{RawTx as Ma,SigHash as qa,Transaction as Da}from"@scure/btc-signer";import{Transaction as ja,keccak256 as Wa,verifyTypedData as Ha}from"ethers";var ge=l(()=>{he();we()});import{base58 as Xa}from"@scure/base";var Z=l(()=>{Q();Y();J();ge()});var nt=l(()=>{Z();Q()});var us,ls,ds,ye=l(()=>{us=Object.freeze({N:1<<17,r:8,p:1}),ls=256*1024*1024,ds=16*1024});var ps,ot=l(()=>{ps=Object.freeze({1:{name:"ethereum",mode:"mempool-private",endpoints:["https://rpc.flashbots.net/fast","https://rpc.mevblocker.io"]},8453:{name:"base",mode:"sequencer",endpoints:["https://mainnet-sequencer.base.org"]},10:{name:"optimism",mode:"sequencer",endpoints:["https://mainnet-sequencer.optimism.io"]},42161:{name:"arbitrum",mode:"sequencer",endpoints:["https://arb1-sequencer.arbitrum.io/rpc"]},56:{name:"bsc",mode:"mempool-private",endpoints:["https://rpc.48.club","https://bsc.rpc.blxrbdn.com"]},137:{name:"polygon",mode:"mempool-private",endpoints:["https://polygon-bor-rpc.publicnode.com"]},43114:{name:"avalanche",mode:"public-only",endpoints:[]},999:{name:"hyperevm",mode:"public-only",endpoints:[]}})});import{homedir as be}from"node:os";import{join as Ee}from"node:path";var it,_r,gs,at=l(()=>{it=process.env.ORACLE_PUBLIC_DESKTOP==="1",_r=it?process.env.ORACLE_CONFIG_DIR||Ee(be(),".config","oracle"):Ee(be(),".config","oracle"),gs=it?_r:Ee(be(),".config","mad-desk")});var Ss,As,vs,st=l(()=>{at();Ss="0".repeat(64),As=Object.freeze({PREPARE:"exec.prepare",SIGN:"exec.sign",BROADCAST:"exec.broadcast",POLICY_REJECT:"policy.reject",AUTH_GRANT:"auth.grant",AUTH_OK:"auth.verify.ok",AUTH_FAIL:"auth.verify.fail"}),vs=Promise.resolve()});var ct=l(()=>{st();N();ye();Z()});var ut=l(()=>{});import{Wallet as Rs}from"ethers";import{base58 as Bs}from"@scure/base";import{ed25519 as Ms}from"@noble/curves/ed25519.js";import{NETWORK as Ds,TEST_NETWORK as Us,WIF as js,p2wpkh as Ws}from"@scure/btc-signer";import{pubECDSA as Js}from"@scure/btc-signer/utils.js";var lt=l(()=>{});import b from"node:path";import Br from"node:os";import{createHash as Fr,randomBytes as Ac}from"node:crypto";import{Interface as xe,keccak256 as kc}from"ethers";import{Transaction as Tc}from"@scure/btc-signer";import{ed25519 as Nc}from"@noble/curves/ed25519.js";function dt(t){let e=process.env.ORACLE_SIGNER_STATE_DIR||b.join(process.env.XDG_STATE_HOME||b.join(Br.homedir(),".local","state"),"oracle"),r=Fr("sha256").update(b.resolve(t)).digest("hex").slice(0,16);return{vault:b.join(t,"vault.json"),policy:b.join(t,"signer-policy.json"),policyKey:b.join(t,"policy-integrity-key"),policyAnchor:b.join(e,`signer-policy-${r}.high-water`),ledger:b.join(t,"signer-ledger.json"),ledgerAnchor:b.join(e,`signer-ledger-${r}.high-water`),token:b.join(t,"signer-token"),lock:b.join(e,`signer-${r}.lock`)}}var Xc,Qc,Zc,ft=l(()=>{nt();Z();ye();ot();ct();ut();J();Q();Y();ge();fe();me();X();we();pe();he();ue();le();lt();Xc=new xe(["function collection() view returns (address)","function token() view returns (address)","function robinhoodSwapFeeWei() view returns (uint256)","function quoteSpecificBuy(uint256 tokenId) view returns (uint256 totalCost,uint256 baseCost,uint256 fee,uint256 protocolFee,bool available)","function quoteSellNFT() view returns (uint256 netPayout,uint256 grossPayout,uint256 fee,uint256 protocolFee)","function inventory(uint256 tokenId) view returns (bool)","function buySpecificNFT(uint256 tokenId,uint256 maxCost) payable","function sellNFT(uint256 tokenId,uint256 minPayout) payable"]),Qc=new xe(["function decimals() view returns (uint8)","function allowance(address owner,address spender) view returns (uint256)"]),Zc=new xe(["function ownerOf(uint256 tokenId) view returns (address)","function getApproved(uint256 tokenId) view returns (address)","function isApprovedForAll(address owner,address operator) view returns (bool)"])});function pt(t){return qr.get(Number(t))||null}var Mr,qr,mt=l(()=>{Mr={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}},qr=new Map(Object.values(Mr).map(t=>[t.chainId,t]))});function c(t){return h(t)?String(t).replace(Dr,e=>`\\${e}`):p}function h(t){return t==null?!1:typeof t=="number"?Number.isFinite(t):typeof t=="string"?t.trim()!=="":!0}function E(t){if(!h(t))return p;let e=String(t).replace(/`/g,"");return e===""?p:`\`${e}\``}function C(t,{decimals:e=2}={}){if(!h(t))return p;let r=Number(t);return Number.isFinite(r)?r.toLocaleString("en-US",{minimumFractionDigits:0,maximumFractionDigits:e}):p}function w(t,{decimals:e=2}={}){let r=C(t,{decimals:e});return r===p?p:`${r} USD`}function Se(t,{decimals:e=2}={}){let r=C(t,{decimals:e});return r===p?p:`${r}%`}function ee(t){let e=C(t,{decimals:0});return e===p?p:`${e} bps`}function $(t,e){if(!h(t))return p;let r=Number(e);if(!Number.isInteger(r)||r<0||r>77)return p;let n;try{n=BigInt(typeof t=="string"?t.trim():t)}catch{return p}let o=n<0n,i=o?-n:n,s=10n**BigInt(r),a=(i/s).toString(),u=(i%s).toString().padStart(r,"0").replace(/0+$/,"");return`${o?"-":""}${a}${u?`.${u}`:""}`}function Ur(t){if(typeof t=="number"&&Number.isFinite(t))return t<0||t>1?p: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 p}function k(t={}){let e=t.chainId;if(!h(e)||!Number.isFinite(Number(e)))return h(t.chain)?c(t.chain):p;let n=pt(e)?.name||(h(t.chain)?String(t.chain):p);return`${c(n)} (chainId ${Number(e)})`}function ht(t={}){return c(t.venue??t.dex??t.pool?.venue)}function jr(t){return t==null?"NONE (text card only)":typeof t=="string"?t.trim()?E(t):"NONE (text card only)":t.error||t.ok===!1||t.available===!1?`UNAVAILABLE${h(t.error)?` \u2014 ${c(t.error)}`:""} (text card stands)`:h(t.url)?E(t.url):"NONE (text card only)"}function Ae(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 n=r.expiresAt??r.expiry;if(h(n)){let i=typeof n=="number"?n:Date.parse(n);if(!Number.isFinite(i))return{allowed:!1,reason:"grant expiry unreadable",actions:[]};if(i<=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 Wr(t){let e=Ae(t);return e.allowed?`${e.actions.map(r=>c(r)).join(" / ")} (${c(e.reason)})`:`prepare-only \u2014 ${c(e.reason)}`}function A(t,e,r={}){let n=[`*${t}*`];for(let[o,i]of e)n.push(`${o}: ${i==null||i===""?p:i}`);return n.push(`Chart: ${jr(r.chart)}`),n.push(`Actions: ${Wr(r)}`),Array.isArray(r.warnings)&&r.warnings.length&&n.push(`Warnings: ${r.warnings.map(o=>c(o)).join("; ")}`),(h(r.source)||h(r.fetchedAt))&&n.push(`Source: ${c(r.source)} at ${c(r.fetchedAt)}`),n.join(`
|
|
3
|
+
`)}function v(t){return["Confidence",Ur(t.confidence)]}function Hr(t){let e=t.quote;if(!e||typeof e!="object")return[];let r=h(e.decimals)?$(e.amountOutRaw??e.out??e.raw,e.decimals):p;return[["Quote out (raw)",E(e.amountOutRaw??e.out??e.raw)],["Quote out",r===p?p:`${c(r)} ${c(e.symbol??"")}`.trim()]]}function wt(t){let e=t.autoSlippage;if(!e||typeof e!="object")return["Auto-slippage",p];let r=ee(e.selectedBps),n=ee(e.capBps);return["Auto-slippage",r===p&&n===p?p:`${r} selected, cap ${n}`]}function Jr(t={}){let e=t||{};return A(`ORACLE TOKEN \u2014 ${c(e.symbol??e.token??e.name)}`,[["Chain",k(e)],["Venue",ht(e)],["Name",c(e.name)],["Address",E(e.address??e.mint??e.contract)],["Price",w(e.priceUsd,{decimals:8})],["Market cap",w(e.marketCapUsd)],["Liquidity",w(e.liquidityUsd)],["Volume 24h",w(e.volume24hUsd)],["Change 24h",Se(e.priceChange24h)],["Fee tier",h(e.feeTier)?`${ee(Number(e.feeTier)/100)} (${C(e.feeTier,{decimals:0})})`:p],["Age",c(e.age)],...Hr(e),wt(e),v(e)],e)}function Gr(t={}){let e=t||{};return A(`ORACLE LAUNCH \u2014 ${c(e.symbol??e.token??e.name)}`,[["Chain",k(e)],["Venue",ht(e)],["Address",E(e.address??e.mint??e.contract)],["Pool",E(e.pool?.address??e.poolAddress??e.pool)],["Liquidity",w(e.liquidityUsd)],["Route ready",c(e.routeReady)],["Sellable",c(e.sellable)],["Sell sim",c(e.sellSimulation??e.sellSim)],["Smart wallets",c(e.smartWalletOverlap)],["Risk",c(e.risk??e.riskStatus)],["Prepared ticket",c(e.preparedTicket??e.ticketStatus)],wt(e),v(e)],e)}function zr(t={}){let e=t||{};return A(`ORACLE HIP-3 \u2014 ${c(e.market??e.coin??e.name)}`,[["Venue",`Hyperliquid builder-dex ${c(e.dex)}`],["Market",c(e.market??e.coin)],["Mark",w(e.markPx,{decimals:6})],["Oracle",w(e.oraclePx,{decimals:6})],["Funding",Se(e.funding,{decimals:6})],["Open interest",w(e.openInterestUsd)],["Depth",c(e.depth)],["Liquidation notes",c(e.liquidationNotes??e.riskNotes)],["Account context",c(e.accountContext)],v(e)],e)}function Vr(t={}){let e=t||{};return A(`ORACLE HIP-4 \u2014 ${c(e.event??e.market??e.name)}`,[["Venue",`Hyperliquid HIP-4 ${c(e.dex??"outcome")}`],["Event",c(e.event)],["Outcome",c(e.outcome)],["Market id",E(e.marketId??e.market)],["Bid",w(e.bid,{decimals:6})],["Ask",w(e.ask,{decimals:6})],["Depth",c(e.depth)],["Edge",Se(e.edge)],["Position",c(e.position)],v(e)],e)}function Kr(t={}){let e=t||{};return A(`ORACLE POLYMARKET \u2014 ${c(e.event??e.market??e.name)}`,[["Venue","Polymarket CLOB"],["Event",c(e.event)],["Market",c(e.market)],["Market id",E(e.marketId??e.conditionId??e.tokenId)],["Yes",w(e.yesPrice,{decimals:4})],["No",w(e.noPrice,{decimals:4})],["Best bid / ask",`${w(e.bestBid,{decimals:4})} / ${w(e.bestAsk,{decimals:4})}`],["Volume",w(e.volumeUsd)],["Resolution risk",c(e.resolutionRisk)],["Order intent",c(e.orderIntent)],v(e)],e)}function Yr(t={}){let e=t||{},r=h(e.completedSplits)&&h(e.totalSplits)?`${C(e.completedSplits,{decimals:0})} / ${C(e.totalSplits,{decimals:0})}`:p;return A(`ORACLE TWAP \u2014 ${c(e.pair??e.symbol??e.name)}`,[["Chain",k(e)],["Side",c(e.side??e.direction)],["Amount",`${c($(e.amountTotal??e.amount,e.decimals??18))} ${c(e.symbol??"")}`.trim()],["Splits",`${C(e.totalSplits,{decimals:0})} over ${c(e.window)}`],["Progress",r],["Avg price",w(e.averagePrice,{decimals:6})],["Next split",c(e.nextSplitAt)],["Slippage cap",ee(e.slippageBps)],["Status",c(e.status)],v(e)],e)}function Xr(t={}){let e=t||{},r=e.approval??e.revokeCheck??{},n=r.needsRevoke&&r.spender?`revoke.cash \u2014 ${c(r.spender)}`:r.needsRevoke===!1?"revoke.cash \u2014 clean":"revoke.cash \u2014 unchecked";return A(`ORACLE BRIDGE \u2014 ${c(e.pair??e.fromSymbol)} \u2192 ${c(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",`${c($(e.amount,e.fromDecimals??18))} ${c(e.fromSymbol??"")}`.trim()],["Best route",c(e.bestRoute??e.winner)],["Est. received",`${c($(e.amountOut,e.toDecimals??18))} ${c(e.toSymbol??"")}`.trim()],["Fee",w(e.feeUsd)],["Est. time",c(e.estimatedTime)],["Revoke check",n],["All providers",c(e.providers?.join(", "))],["Preparable",c(e.preparable)],v(e)],e)}function Qr(t){let r=(Array.isArray(t)?t:[]).slice(1,4).map(n=>{let o=c(n.source??n.venue??n.name),i=n.improvementBps==null&&n.deltaBps==null?null:Number(n.improvementBps??n.deltaBps),s=Number.isFinite(i)?`${Math.abs(i).toFixed(0)} bps behind`:"spread UNKNOWN";return`${o} (${s})`});return r.length?r.join("; "):p}function Zr(t){let e=t.rankedOn??t.swap?.rankedOn??t.best?.rankedOn;return h(e)?c(e):p}function en(t={}){let e=t||{},r=e.swap&&typeof e.swap=="object"?e.swap:e,n=e.bridge&&typeof e.bridge=="object"?e.bridge:null,o=r.best??r.winner??{},i=`${c(e.tokenInSymbol??e.fromSymbol??"IN")} \u2192 ${c(e.tokenOutSymbol??e.toSymbol??"OUT")}`,s=[["Intent",c(e.intent??"swap")],["Chain",k({chainId:e.chainId??r.chainId,chain:e.chain??r.chain})],["Pair",i],["Amount in",`${c($(e.amountIn??r.amountIn,e.decimalsIn??18))} ${c(e.tokenInSymbol??"")}`.trim()],["Best swap",c(o.source??o.venue??r.bestRoute??e.bestRoute)],["Net out",`${c($(o.netOut??o.amountOut??r.amountOut,e.decimalsOut??18))} ${c(e.tokenOutSymbol??"")}`.trim()],["Ranked on",Zr(r)],["Gas accounted",c(o.costAccounted===!0?"yes":o.costAccounted===!1?"no \u2014 gross ranking may flatter this route":null)],["Spread vs next",h(r.improvementBps)?`${c(r.improvementBps)} bps`:p],["Runners-up",Qr(r.routes??e.routes)]];if(n){let a=n.best??n.winner??{};s.push(["Best bridge",c(a.source??n.bestRoute??e.bestBridge)],["Bridge out",`${c($(a.netOut??a.amountOut??n.amountOut,e.bridgeDecimalsOut??e.decimalsOut??18))} ${c(e.bridgeOutSymbol??e.tokenOutSymbol??"")}`.trim()],["Bridge to",k({chainId:n.toChainId??e.toChainId,chain:n.toChain??e.toChain})],["Est. time",c(n.estimatedTime??a.meta?.durationSeconds)])}else s.push(["Best bridge","same-chain \u2014 use Best swap"]);return s.push(["Preparable",c(e.preparable??o.executionReady)],v(e)),A(`ORACLE SWAP \u2014 ${i}`,s,e)}function ve(t={}){let e=t||{};return A("ORACLE APPROVE \u2014 local signer",[["Pending id",E(e.id??(typeof e.digest=="string"?e.digest.slice(0,8):null))],["Surface",c(e.surface)],["Action",c(e.action)],["Chain",k({chainId:e.chain??e.chainId,chain:e.chainName})],["To",E(e.to??e.destination)],["Value",h(e.value)?c(e.value):p],["Signer",c(e.armed===!0?"running + armed":e.armed===!1?"running, disarmed":"not running")],v({confidence:e.confidence??(e.armed===!0?"high":"low")})],e)}function ke({platform:t="telegram",id:e,digest:r,hasGrant:n=!1}={}){let o=String(e||(typeof r=="string"?r.slice(0,8):"")||"").trim();return n?o?String(t)==="telegram"?{kind:"inline_keyboard",replyMarkup:{inline_keyboard:[[{text:"Allow",callback_data:`oracle:approve:${o}`},{text:"Deny",callback_data:`oracle:deny:${o}`}]]},cancelHint:"Allow signs with the local signer. Deny drops the pending artifact."}:{kind:"text_menu",text:["1. Allow \u2014 reply /approve "+o,"2. Deny \u2014 reply /deny "+o].join(`
|
|
4
|
+
`),cancelHint:"Cards are not available on this chat. Use /approve or /deny."}:{kind:"text_menu",text:"nothing to approve",cancelHint:""}:String(t)==="telegram"?{kind:"inline_keyboard",replyMarkup:{inline_keyboard:[]},cancelHint:"prepare-only \u2014 no local grant/session"}:{kind:"text_menu",text:"prepare-only \u2014 no local grant/session",cancelHint:""}}var p,nu,Dr,ou,gt=l(()=>{mt();p="UNKNOWN",nu=Object.freeze(["token","launch","hip3","hip4","polymarket","twap","bridge","swap","approve"]),Dr=/[_*[\]`]/g;ou=Object.freeze({token:Jr,launch:Gr,hip3:zr,hip4:Vr,polymarket:Kr,twap:Yr,bridge:Xr,swap:en,approve:ve})});import{readFileSync as tn,existsSync as rn}from"node:fs";import{request as nn}from"node:http";function an(t=process.env){let e=String(t.ORACLE_SIGNER_URL||on).replace(/\/$/,""),r;try{r=new URL(e)}catch{return null}return r.hostname!=="127.0.0.1"&&r.hostname!=="localhost"&&r.hostname!=="::1"?null:r.origin}function sn(t=process.env){if(t.ORACLE_SIGNER_TOKEN)return String(t.ORACLE_SIGNER_TOKEN);let e=dt(`${P()}/signer`).token;return rn(e)?tn(e,"utf8").trim():null}function yt(t,{method:e="GET",body:r=null,env:n=process.env,timeoutMs:o=4e3}={}){let i=an(n),s=sn(n);return!i||!s?Promise.resolve({ok:!1,error:"local signer is not running"}):new Promise(a=>{let u=new URL(t,i),d=r?Buffer.from(JSON.stringify(r)):null,f=nn({hostname:u.hostname,port:u.port||80,path:u.pathname,method:e,timeout:o,headers:{authorization:`Bearer ${s}`,origin:i,...d?{"content-type":"application/json","content-length":d.length}:{}}},m=>{let g=[];m.on("data",x=>g.push(x)),m.on("end",()=>{let x=Buffer.concat(g).toString("utf8"),S={};try{S=x?JSON.parse(x):{}}catch{S={error:"signer refused"}}a({httpStatus:m.statusCode,...S})})});f.on("timeout",()=>{f.destroy(),a({ok:!1,error:"local signer timed out"})}),f.on("error",()=>a({ok:!1,error:"local signer is not running"})),d&&f.write(d),f.end()})}function Ie(t){let r=String(t||"").trim().match(/^\/(approve|deny|pending)(?:@[\w_]+)?(?:\s+([0-9a-fA-F]{4,64}))?\s*$/i);return r?{verb:r[1].toLowerCase(),id:r[2]?r[2].toLowerCase():null}:null}function cn(t,{platform:e,grant:r,armed:n}){if(!t.length)return{text:"No pending local-signer artifacts.",buttons:ke({platform:e,hasGrant:!1})};let o=t[0];return{text:t.map(s=>ve({...s,armed:n,grant:r,confidence:n?"high":"medium"})).join(`
|
|
5
|
+
|
|
6
|
+
`),buttons:ke({platform:e,id:o.id,digest:o.digest,hasGrant:Ae({grant:r}).allowed})}}async function Te({platform:t,text:e,grant:r={local:!0},env:n=process.env}={}){let o=Ie(e);if(!o)return null;let i=String(t)==="telegram";if(i&&o.verb!=="pending"&&!o.id)return{text:"On Telegram, tap Allow or Deny on the approve card. /approve is only for chats without cards.",buttons:null};if(o.verb==="pending"){let u=await yt("/pending",{env:n});if(u.ok===!1||u.error)return{text:`Local signer: ${u.error||"not running"}. Start \`oracle signer\` on this machine first.`,buttons:null};let d=Array.isArray(u.items)?u.items:[],f=cn(d,{platform:t,grant:r,armed:u.armed===!0});if(i)return f;if(!d.length)return{text:"No pending local-signer artifacts. /approve is only needed when cards are unavailable.",buttons:null};let m=d.map(g=>`\u2022 ${g.id} ${g.surface}/${g.action} to ${g.to||"n/a"}`);return m.push("Cards are not available here. Reply /approve <id> or /deny <id>."),{text:m.join(`
|
|
7
|
+
`),buttons:null}}let s=o.verb==="approve"?"/ack":"/deny";if(!o.id)return{text:"Usage: /approve <id> (only when approve cards are not available)",buttons:null};let a=await yt(s,{method:"POST",body:{id:o.id},env:n});return a.httpStatus===404||a.error==="no pending artifact"?{text:"Nothing pending with that id. It may have expired or already been decided.",buttons:null}:a.ok===!1||a.httpStatus&&a.httpStatus>=400?{text:`Local signer refused: ${a.error||"not running"}`,buttons:null}:o.verb==="deny"?{text:`Denied ${a.id||o.id}. Artifact dropped. Nothing signed.`,buttons:null}:{text:`Approved ${a.id||o.id}. Confirmation issued to the local signer. It still must execute the confirmed artifact; this chat did not broadcast.`,buttons:null,confirmationNonce:a.confirmationNonce||null}}async function bt({platform:t,data:e,grant:r={local:!0},env:n=process.env}={}){let i=String(e||"").match(/^oracle:(approve|deny):([0-9a-fA-F]{4,64})$/i);if(!i)return null;let s=i[1].toLowerCase()==="approve"?"approve":"deny";return Te({platform:t,text:`/${s} ${i[2]}`,grant:r,env:n})}var on,Oe=l(()=>{ne();ft();gt();on="http://127.0.0.1:9462"});import{execFile as un}from"node:child_process";import{existsSync as ln,mkdirSync as dn,readFileSync as Et,realpathSync as fn,writeFileSync as pn}from"node:fs";import I from"node:path";import{promisify as mn}from"node:util";import{fileURLToPath as xt}from"node:url";function yn(t=import.meta.url){try{let e=fn(xt(t)),r=`${I.sep}node_modules${I.sep}`,n=e.lastIndexOf(r);if(n>0)return{root:e.slice(0,n),managed:!0}}catch{}return{root:null,managed:!1}}function Ce(t=import.meta.url){try{let e=I.dirname(xt(t));for(let r=0;r<8;r+=1){let n=I.join(e,"package.json");if(ln(n)){let i=JSON.parse(Et(n,"utf8"));if(i?.name===Ne&&i.version)return i.version}let o=I.dirname(e);if(o===e)break;e=o}}catch{return null}return null}function bn(t,e){let r=i=>String(i).replace(/^v/,"").split("-")[0].split(".").map(s=>Number.parseInt(s,10)||0),n=r(t),o=r(e);for(let i=0;i<Math.max(n.length,o.length);i+=1){let s=n[i]??0,a=o[i]??0;if(s>a)return 1;if(s<a)return-1}return 0}function St(t){let e=t?.stateDir||I.join(process.env.HOME||".",".oracle");return I.join(e,"update-check.json")}function En(t){try{return JSON.parse(Et(St(t),"utf8"))}catch{return null}}function xn(t,e){try{let r=St(t);dn(I.dirname(r),{recursive:!0}),pn(r,`${JSON.stringify(e,null,2)}
|
|
8
|
+
`)}catch{}}async function Sn({timeoutMs:t=4e3}={}){try{let e=new AbortController,r=setTimeout(()=>e.abort(),t),n=await fetch(`${wn}/${encodeURIComponent(Ne)}/latest`,{signal:e.signal});return clearTimeout(r),n.ok&&(await n.json())?.version||null}catch{return null}}async function At({paths:t,force:e=!1,timeoutMs:r=4e3}={}){let n=Ce(),o=e?null:En(t),s=o&&Date.now()-(o.checkedAt||0)<gn?o.latest:null;return s||(s=await Sn({timeoutMs:r}),s&&xn(t,{latest:s,checkedAt:Date.now()})),!n||!s?{current:n,latest:s,updateAvailable:!1,checked:!!s}:{current:n,latest:s,updateAvailable:bn(s,n)>0,checked:!0}}async function vt({version:t="latest",dryRun:e=!1}={}){let{root:r,managed:n}=yn();if(!n||!r)return{ok:!1,reason:"unmanaged",message:`oracle is not running from a resolvable node_modules tree (source checkout or linked dev install).
|
|
9
|
+
Update it the same way you installed it \u2014 git pull, or npm install -g @oracle-agent/oracle@latest.`};let o=`${Ne}@${t}`,i=["install","--prefix",r,"--no-audit","--no-fund",o];if(e)return{ok:!0,dryRun:!0,root:r,command:`npm ${i.join(" ")}`};try{let{stdout:s,stderr:a}=await hn("npm",i,{timeout:3e5,maxBuffer:16777216});return{ok:!0,root:r,stdout:s,stderr:a}}catch(s){return{ok:!1,reason:"npm-failed",root:r,message:s?.stderr||s?.message||"npm install failed"}}}var hn,Ne,wn,gn,kt=l(()=>{hn=mn(un),Ne="@oracle-agent/oracle",wn="https://registry.npmjs.org",gn=1440*60*1e3});var Mt={};L(Mt,{NON_OWNER_REPLY:()=>q,buildPersona:()=>D,handleSelfUpdate:()=>$t,isForwarded:()=>Lt,isOwnerSender:()=>M,ownerIdsFor:()=>Nt,parsePeerAsk:()=>Rt,parseSelfUpdate:()=>Ct,resolveBackendArgv:()=>Pt,resolveGatewayModel:()=>_t,routePeerConsult:()=>G,routeToAgent:()=>T});import{spawn as It}from"node:child_process";import{join as Tt}from"node:path";import{homedir as Ot}from"node:os";function Nt(t,e=process.env){let r=String(e[`ORACLE_OWNER_${String(t).toUpperCase()}`]||""),n=String(e.ORACLE_OWNER_IDS||"");return new Set(`${r},${n}`.split(",").map(o=>o.trim()).filter(Boolean))}function M({platform:t,senderId:e,extraOwners:r},n=process.env){let o=String(e||"").trim();return o?Nt(t,n).has(o)?!0:Array.isArray(r)?r.map(i=>String(i).trim()).filter(Boolean).includes(o):!1:!1}function Ct(t){let e=String(t||"").trim();if(!e)return null;let r=e.replace(/^\/update(?:@[\w_]+)?\b/i,"update");return/^(?:oracle\s+)?update\s+--check\s*$/i.test(r)?{checkOnly:!0}:/^(?:oracle\s+)?update\s*$/i.test(r)?{checkOnly:!1}:null}async function $t(t,{check:e=At,update:r=vt,versionOf:n=Ce}={}){let o=await e({force:!0});if(t.checkOnly)return o.checked?o.updateAvailable?`oracle ${o.current} \u2192 ${o.latest} available. Send /update to install.`:`oracle ${o.current} is up to date`:`oracle ${o.current||"?"} \u2014 could not reach npm`;if(o.checked&&!o.updateAvailable)return`oracle ${o.current} is already up to date`;let i=o.latest||"latest",s=await r({version:i==="latest"?"latest":i});if(!s.ok)return`oracle update failed: ${s.message}`;let a=n();return[`oracle ${o.current||"?"} \u2192 ${a||i}`,"Restart the gateway to load it: oracle gateway"].join(`
|
|
10
|
+
`)}function Lt(t={}){return!!(t.forwarded||t.forward_from||t.forward_from_chat||t.forward_origin||t.forward_sender_name||t.forward_date)}function _t({readConfig:t=De}={}){let e=t();return e?e.backend==="hermes"?{ok:!1,error:"model config delegates to hermes; the gateway runs Oracle's native loop. Set a standalone backend: oracle model --backend standalone"}:e.model?{ok:!0,provider:e.provider,model:e.model}:{ok:!1,error:"model config has no model \u2014 run: oracle model --backend standalone --provider <p> --model <m>"}:{ok:!1,error:"gateway has no model configured \u2014 run: oracle model --backend standalone --provider <p> --model <m>"}}function Rt(t){let e=String(t||"").trim();if(!e)return null;let r=e.match(/^\/ask(?:@[\w_]+)?\s+([\w-]+)\s+([\s\S]+)$/i);return r||(r=e.match(/^@([\w-]+)\s+([\s\S]+)$/)),r?{peer:r[1].toLowerCase(),text:r[2].trim()}:null}function D(t={}){let e=[];return t.role&&e.push(String(t.role)),Array.isArray(t.chains)&&t.chains.length&&e.push(`chains: ${t.chains.join(", ")}`),t.persona&&e.push(String(t.persona)),e.join(" \xB7 ")}function Pt(t,e,{profile:r}={}){let n=String(t||"oracle").toLowerCase(),o=String(e||"");if(n==="oracle")return{ok:!0,bin:null,args:["chat","-q",o]};if(n==="grok")return{ok:!0,bin:"grok",args:["-p",o]};if(n==="hermes"){let i=[];return r&&i.push("-p",String(r)),i.push("-z",o),{ok:!0,bin:"hermes",args:i}}return n==="claude"?{ok:!0,bin:"claude",args:["-p",o]}:{ok:!1,error:`unknown backend '${t}' (allowed: oracle, grok, hermes, claude)`}}async function G({from:t,text:e,persona:r="",backend:n,profile:o}={}){let i=[`[a2a consult from agent '${t}' \u2014 answer with information only; do not prepare, arm, or execute anything]`,r?`[your role: ${r}]`:"",String(e||"").trim()].filter(Boolean).join(`
|
|
11
|
+
`);return Ft({text:i,backend:n,profile:o,unconfiguredPrefix:"unconfigured: "})}async function T({platform:t,chatId:e,senderId:r,text:n,userName:o,meta:i={},updater:s,extraOwners:a,bus:u,agentName:d,persona:f,backend:m,profile:g}={}){if(!M({platform:t,senderId:r,extraOwners:a}))return process.stderr.write(`gateway: denied non-owner sender ${t}:${String(r||"unknown")}
|
|
12
|
+
`),q;if(Lt(i))return process.stderr.write(`gateway: dropped forwarded message on ${t}
|
|
13
|
+
`),null;let x=Ct(n);if(x)return $t(x,s);if(Ie(n)){let y=await Te({platform:t,text:n,grant:{local:!0}});return y?y.buttons?.kind==="inline_keyboard"?{text:y.text,replyMarkup:y.buttons.replyMarkup}:y.text:null}if(u){let y=Rt(n);if(y){let O=await u.send({from:d||"oracle",to:y.peer,text:y.text,kind:"consult"});return O.ok?O.reply?`[${y.peer}] ${O.reply}`:`[${y.peer}] (no reply)`:O.error}if(/^\/(agents|roster)\b/i.test(String(n||"").trim())){let O=u.roster().map(j=>`\u2022 ${j.name}${j.role?` \u2014 ${j.role}`:""}${j.chains.length?` (${j.chains.join(", ")})`:""}`);return O.length?`Agents on the bus:
|
|
14
|
+
${O.join(`
|
|
15
|
+
`)}`:"No peer agents registered."}}let er=n.toLowerCase().trim();return/\b(buy|sell|swap|bridge|send|transfer|balance|portfolio|watch|quote|price)\b/.test(er)?In({platform:t,chatId:e,senderId:r,text:n,userName:o}):Tn({platform:t,chatId:e,senderId:r,text:n,userName:o,persona:f,backend:m,profile:g})}function Bt(t,{timeout:e=12e4}={}){return new Promise(r=>{let n=It(process.execPath,[vn,...t],{stdio:["ignore","pipe","pipe"],timeout:e,env:{...process.env,ORACLE_CONFIG_DIR:An}}),o="",i="";n.stdout.on("data",s=>o+=s.toString()),n.stderr.on("data",s=>i+=s.toString()),n.on("close",s=>r({code:s,out:o.trim(),err:i.trim()}))})}function kn(t,e,{timeout:r=18e4}={}){return new Promise(n=>{let o=It(t,e,{stdio:["ignore","pipe","pipe"],timeout:r,env:{...process.env}}),i="",s="";o.on("error",a=>n({code:127,out:"",err:String(a.message)})),o.stdout.on("data",a=>i+=a.toString()),o.stderr.on("data",a=>s+=a.toString()),o.on("close",a=>n({code:a,out:i.trim(),err:s.trim()}))})}async function In({text:t}){let e=await Bt(["route","swap","--text",t],{timeout:3e4});if(e.code===0&&e.out)try{return On(JSON.parse(e.out))}catch{return e.out}return`Trade routing failed. Try: \`${t}\` again.`}async function Tn({text:t,persona:e,backend:r,profile:n}){let o=e?`[your role: ${e}]
|
|
16
|
+
${t}`:t;return Ft({text:o,backend:r,profile:n,unconfiguredPrefix:"Oracle is not configured yet: "})}async function Ft({text:t,backend:e,profile:r,unconfiguredPrefix:n}){let o=Pt(e,t,{profile:r});if(!o.ok)return`${n}${o.error}`;if(!o.bin){let s=_t();if(!s.ok)return`${n}${s.error}`;let a=await Bt(o.args);return a.code===0&&a.out?a.out:a.err||"Oracle could not answer that. Try again."}let i=await kn(o.bin,o.args);return i.code===0&&i.out?i.out:/ENOENT/.test(i.err)?`${n}backend '${o.bin}' is not installed on this machine`:i.err||`${o.bin} could not answer that. Try again.`}function On(t){return t.error?`\u274C ${t.error}`:t.tx?`\u2705 Trade prepared: \`${t.tx.slice(0,20)}...\`
|
|
17
|
+
Sign and broadcast from your own wallet.`:t.quote?`\u{1F4B1} ${t.quote}`:t.portfolio?`\u{1F4CA} ${t.portfolio}`:JSON.stringify(t,null,2)}var An,vn,q,U=l(()=>{Ue();Oe();kt();An=process.env.ORACLE_CONFIG_DIR||Tt(Ot(),".config","oracle"),vn=process.env.ORACLE_CLI_ENTRY||Tt(Ot(),".local","share","oracle-stable","node_modules","@oracle-agent","oracle","bin","oracle.mjs");q="Oracle is self-hostable. Install your own instance: npm install -g @oracle-agent/oracle"});var Dt={};L(Dt,{buildPersona:()=>D,telegram:()=>Nn});function qt(t,e){if(!e)return;if(typeof e=="string")return t.reply(e,{parse_mode:"Markdown"});let r=e.replyMarkup?{reply_markup:e.replyMarkup}:{};return t.reply(e.text,{parse_mode:"Markdown",...r})}async function Nn(t){let{Bot:e}=await import("grammy"),r=new e(t.token),n=String(t.name||"oracle").toLowerCase(),o=D(t),i=Array.isArray(t.owners)?t.owners:void 0,s=t.bus;return s&&s.register(n,{role:t.role||"",chains:t.chains||[],handler:a=>G({from:a.from,text:a.text,persona:o,backend:t.backend,profile:t.hermesProfile})}),r.command("start",a=>{let u=String(a.from?.id||a.chat.id);return M({platform:"telegram",senderId:u,extraOwners:i})?a.reply(`${n} ready. Ask me anything \u2014 swap, bridge, portfolio, watch. /update installs latest.${s?" /agents lists peers.":""}`):a.reply(q)}),r.command("update",async a=>{let u=String(a.from?.id||a.chat.id),d=String(a.chat.id);if(!M({platform:"telegram",senderId:u,extraOwners:i}))return a.reply(q);if(a.message.forward_origin||a.message.forward_from||a.message.forward_date)return;a.replyWithChatAction("typing").catch(()=>{});let f=await T({platform:"telegram",chatId:d,senderId:u,text:a.match?`update ${a.match}`.trim():"update",userName:a.from?.username||a.from?.first_name||"user"});if(f)return qt(a,f)}),r.on("message:text",async a=>{let u=String(a.chat.id),d=String(a.from?.id||u),f=a.message.text;try{a.replyWithChatAction("typing").catch(()=>{});let m=await T({platform:"telegram",chatId:u,senderId:d,text:f,userName:a.from?.username||a.from?.first_name||"user",extraOwners:i,bus:s,agentName:n,persona:o,backend:t.backend,profile:t.hermesProfile,meta:{forward_origin:a.message.forward_origin,forward_from:a.message.forward_from,forward_from_chat:a.message.forward_from_chat,forward_sender_name:a.message.forward_sender_name,forward_date:a.message.forward_date}});m&&await qt(a,m)}catch(m){process.stderr.write(`telegram-gateway[${n}]: ${m.message}
|
|
18
|
+
`),await a.reply("Something went wrong. Try again.").catch(()=>{})}}),r.on("callback_query:data",async a=>{let u=String(a.from?.id||"");if(!M({platform:"telegram",senderId:u,extraOwners:i})){await a.answerCallbackQuery({text:q.slice(0,180),show_alert:!0}).catch(()=>{});return}let d=String(a.callbackQuery?.data||""),f=await bt({platform:"telegram",data:d,grant:{local:!0}});if(!f){await a.answerCallbackQuery().catch(()=>{});return}await a.answerCallbackQuery({text:"ok"}).catch(()=>{}),f.text&&await a.reply(f.text,{parse_mode:"Markdown"}).catch(()=>{})}),r.start(),{platform:"telegram",name:n,bot:r}}var Ut=l(()=>{U();Oe()});var jt={};L(jt,{discord:()=>Cn});async function Cn(t){let{Client:e,GatewayIntentBits:r}=await import("discord.js"),n=new e({intents:[r.Guilds,r.GuildMessages,r.MessageContent,r.DirectMessages]}),o=String(t.name||"oracle").toLowerCase(),i=D(t),s=Array.isArray(t.owners)?t.owners:void 0,a=t.bus;return a&&a.register(o,{role:t.role||"",chains:t.chains||[],handler:u=>G({from:u.from,text:u.text,persona:i,backend:t.backend,profile:t.hermesProfile})}),n.on("messageCreate",async u=>{if(u.author.bot)return;let d=u.channel.id,f=u.author.id,m=u.content;try{let g=!u.guild,x=u.mentions.has(n.user.id);if(!g&&!x)return;u.channel.sendTyping().catch(()=>{});let S=await T({platform:"discord",chatId:d,senderId:f,text:m.replace(`<@${n.user.id}>`,"").trim(),userName:u.author.username,extraOwners:s,bus:a,agentName:o,persona:i,backend:t.backend,profile:t.hermesProfile,meta:{forwarded:u.reference?.type===1||Array.isArray(u.messageSnapshots)&&u.messageSnapshots.length>0}});S&&await u.reply(typeof S=="string"?S:S.text).catch(()=>{})}catch(g){process.stderr.write(`discord-gateway[${o}]: ${g.message}
|
|
19
|
+
`)}}),await n.login(t.token),{platform:"discord",name:o,client:n}}var Wt=l(()=>{U()});var Jt={};L(Jt,{whatsapp:()=>_n});import{join as Ht}from"node:path";import{homedir as $n}from"node:os";async function _n(t){let[{Client:e,LocalAuth:r},{generate:n}]=await Promise.all([import("whatsapp-web.js"),import("qrcode-terminal")]),o=new e({authStrategy:new r({dataPath:Ht(Ln,".wwebjs_auth")}),puppeteer:{headless:!0,args:["--no-sandbox"]}});return o.on("qr",i=>{process.stderr.write(`
|
|
15
20
|
WhatsApp: scan this QR code in WhatsApp \u2192 Linked Devices:
|
|
16
21
|
|
|
17
|
-
`),
|
|
22
|
+
`),n(i,{small:!0}),process.stderr.write(`
|
|
18
23
|
`)}),o.on("ready",()=>{process.stderr.write(`whatsapp-gateway: connected
|
|
19
|
-
`)}),o.on("message",async
|
|
20
|
-
`)}}),await o.initialize(),{platform:"whatsapp",client:o}}var
|
|
24
|
+
`)}),o.on("message",async i=>{if(i.fromMe)return;let s=i.from,a=i.author||i.from,u=i.body;try{let d=await T({platform:"whatsapp",chatId:s,senderId:a,text:u,userName:i._data?.notifyName||"user",meta:{forwarded:i.isForwarded||i._data?.isForwarded,forward_date:i._data?.forwardingScore?!0:void 0}});if(d){let m=(typeof d=="string"?d:d.text).replace(/\*\*/g,"*").replace(/```[\s\S]*?```/g,"[code]").replace(/`/g,"");await i.reply(m)}}catch(d){process.stderr.write(`whatsapp-gateway: ${d.message}
|
|
25
|
+
`)}}),await o.initialize(),{platform:"whatsapp",client:o}}var Ln,Gt=l(()=>{U();Ln=process.env.ORACLE_CONFIG_DIR||Ht($n(),".config","oracle")});var zt={};L(zt,{signal_:()=>Rn});async function Rn(t){return process.stderr.write(`signal-gateway: requires signal-cli binary
|
|
21
26
|
`),process.stderr.write(`signal-gateway: not built yet \u2014 use Telegram or Discord for now
|
|
22
|
-
`),{platform:"signal",status:"stub"}}var
|
|
23
|
-
npm install -g ${
|
|
24
|
-
`);return}process.stderr.write(`oracle-gateway: ${
|
|
25
|
-
`)}}async function
|
|
26
|
-
`)}catch(
|
|
27
|
-
`)}}for(let
|
|
28
|
-
`),process.stderr.write(`oracle-gateway: ${
|
|
29
|
-
`);let s
|
|
30
|
-
`)}var
|
|
31
|
-
`,{mode:384}),r}var{pathToFileURL:
|
|
32
|
-
`),process.exit(1)});export{
|
|
27
|
+
`),{platform:"signal",status:"stub"}}var Vt=l(()=>{U()});import{createServer as Pn}from"node:http";import{env as Xt}from"node:process";import{join as _e}from"node:path";import{homedir as Bn}from"node:os";import{readFileSync as Qt,existsSync as Fn,mkdirSync as Mn,writeFileSync as qn}from"node:fs";import{randomBytes as Dn}from"node:crypto";var Zt=Xt.ORACLE_CONFIG_DIR||_e(Bn(),".config","oracle"),Kt=_e(Zt,"gateway.json");function Un(){return Fn(Kt)?JSON.parse(Qt(Kt,"utf8")):{platforms:{}}}function $e(t){return t?Array.isArray(t)?t.filter(Boolean):[t]:[]}var jn=Object.freeze({telegram:"grammy",discord:"discord.js",whatsapp:"whatsapp-web.js"});async function te(t,e,r,n){try{n.push(await e(r))}catch(o){let i=jn[t];if(i&&/Cannot find (module|package)|ERR_MODULE_NOT_FOUND/.test(String(o.message))){process.stderr.write(`oracle-gateway: ${t} needs an optional dependency. Install it first:
|
|
28
|
+
npm install -g ${i}
|
|
29
|
+
`);return}process.stderr.write(`oracle-gateway: ${t} failed to start: ${o.message}
|
|
30
|
+
`)}}async function Wn(){let t=Un(),e=[],r=$e(t.platforms?.telegram),n=$e(t.platforms?.discord),o=$e(t.agents),s=r.length+n.length+o.length>1?new(await Promise.resolve().then(()=>(Pe(),Re))).A2ABus:null;if(s&&o.length){let{routePeerConsult:u,buildPersona:d}=await Promise.resolve().then(()=>(U(),Mt));for(let f of o)try{let m=d(f);s.register(f.name,{role:f.role||"",chains:f.chains||[],handler:g=>u({from:g.from,text:g.text,persona:m,backend:f.backend,profile:f.hermesProfile})}),process.stderr.write(`oracle-gateway: headless agent '${f.name}' on bus (backend: ${f.backend||"oracle"})
|
|
31
|
+
`)}catch(m){process.stderr.write(`oracle-gateway: headless agent '${f.name||"?"}' skipped: ${m.message}
|
|
32
|
+
`)}}for(let u of r)await te("telegram",async()=>(await Promise.resolve().then(()=>(Ut(),Dt))).telegram({...u,bus:s}),t,e);for(let u of n)await te("discord",async()=>(await Promise.resolve().then(()=>(Wt(),jt))).discord({...u,bus:s}),t,e);t.platforms?.whatsapp&&await te("whatsapp",async u=>(await Promise.resolve().then(()=>(Gt(),Jt))).whatsapp(u.platforms.whatsapp),t,e),t.platforms?.signal&&await te("signal",async u=>(await Promise.resolve().then(()=>(Vt(),zt))).signal_(u.platforms.signal),t,e),e.length===0&&process.stderr.write(`oracle-gateway: no platforms configured. Run 'oracle setup telegram' first.
|
|
33
|
+
`),process.stderr.write(`oracle-gateway: ${e.length} platform(s) connected
|
|
34
|
+
`);let a=s?zn():null;Pn((u,d)=>Jn(u,d,{config:t,bus:s,a2aToken:a})).listen(Xt.ORACLE_GATEWAY_PORT||9270,"127.0.0.1"),s&&process.stderr.write(`oracle-gateway: a2a loopback contract at GET /a2a (token: a2a-token in config dir)
|
|
35
|
+
`)}var Hn=16384;async function Jn(t,e,{config:r,bus:n,a2aToken:o}){let i=new URL(t.url||"/","http://127.0.0.1"),s=(u,d)=>{e.writeHead(u,{"Content-Type":"application/json"}),e.end(JSON.stringify(d))};if(t.method==="GET"&&(i.pathname==="/"||i.pathname==="/health"))return s(200,{status:"ok",platforms:Object.keys(r.platforms||{}),a2a:!!n});if(!i.pathname.startsWith("/a2a"))return s(404,{error:"not found"});if(!n)return s(404,{error:"a2a bus not running (fewer than 2 agents configured)"});if(t.method==="GET"&&i.pathname==="/a2a")return s(200,{contract:"oracle-a2a/1",auth:"Authorization: Bearer <contents of a2a-token in the oracle config dir>",endpoints:["GET /a2a","GET /a2a/agents","POST /a2a/ask {to,text,from?}"],note:"consult-only; loopback-only; peers answer with information, never actions"});let a=String(t.headers.authorization||"");if(!o||a!==`Bearer ${o}`)return s(401,{error:"bad or missing bearer token (read a2a-token in the oracle config dir)"});if(t.method==="GET"&&i.pathname==="/a2a/agents")return s(200,{agents:n.roster()});if(t.method==="POST"&&i.pathname==="/a2a/ask"){let u="";t.on("data",d=>{u+=d,u.length>Hn&&t.destroy()}),t.on("end",async()=>{try{let d=JSON.parse(u||"{}"),f=Gn(d.from);n.agents.has(f)||n.register(f,{role:"loopback client",handler:async()=>null});let m=await n.send({from:f,to:d.to,text:d.text,kind:"consult"});return s(m.ok?200:400,m)}catch(d){return s(400,{ok:!1,error:`bad request: ${d.message}`})}});return}return s(404,{error:"not found"})}function Gn(t){return String(t||"local").trim().toLowerCase().replace(/[^a-z0-9_-]/g,"").slice(0,32)||"local"}function zn(t=Zt){let e=_e(t,"a2a-token");try{let n=Qt(e,"utf8").trim();if(n)return n}catch{}let r=Dn(24).toString("hex");return Mn(t,{recursive:!0}),qn(e,`${r}
|
|
36
|
+
`,{mode:384}),r}var{pathToFileURL:Vn}=await import("node:url"),{realpathSync:Kn}=await import("node:fs"),Yt=process.argv[1],Le=!1;if(Yt)try{Le=import.meta.url===Vn(Kn(Yt)).href}catch{Le=!1}Le&&Wn().catch(t=>{process.stderr.write(`oracle-gateway: ${t.message}
|
|
37
|
+
`),process.exit(1)});export{zn as ensureA2AToken,Jn as serveHttp,$e as toEntries};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var cr=Object.defineProperty;var P=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(n){throw r=[n],n}};var Xe=(e,t)=>{for(var r in t)cr(e,r,{get:t[r],enumerable:!0})};import z from"node:net";import ur from"node:dns";function re(e){let t=String(e).toLowerCase().split("%")[0];if((t.match(/::/g)||[]).length>1)return null;let r=d=>{if(!d)return[];let c=d.split(":"),i=c.at(-1);if(i?.includes(".")){let p=i.split(".").map(Number);if(p.length!==4||p.some(m=>!Number.isInteger(m)||m<0||m>255))return null;c.splice(c.length-1,1,(p[0]<<8|p[1]).toString(16),(p[2]<<8|p[3]).toString(16))}return c.some(p=>!/^[0-9a-f]{1,4}$/.test(p))?null:c.map(p=>Number.parseInt(p,16))},[n,o]=t.split("::"),s=r(n),a=r(o);if(!s||!a)return null;let u=t.includes("::"),l=8-s.length-a.length;if(!u&&l!==0||u&&l<1)return null;let f=[...s,...Array(Math.max(0,l)).fill(0),...a];return f.length!==8?null:Uint8Array.from(f.flatMap(d=>[d>>8,d&255]))}function ye(e,t,r){let n=Math.floor(r/8),o=r%8;for(let a=0;a<n;a+=1)if(e[a]!==t[a])return!1;if(!o)return!0;let s=255<<8-o;return(e[n]&s)===(t[n]&s)}function Ae(e){if(z.isIPv4(e)){let t=e.split(".").map(Number);return!(t[0]===0||t[0]===10||t[0]===127||t[0]>=224||t[0]===100&&t[1]>=64&&t[1]<=127||t[0]===169&&t[1]===254||t[0]===172&&t[1]>=16&&t[1]<=31||t[0]===192&&(t[1]===0||t[1]===2||t[1]===168)||t[0]===192&&t[1]===88&&t[2]===99||t[0]===198&&(t[1]===18||t[1]===19||t[1]===51)||t[0]===203&&t[1]===0&&t[2]===113)}if(z.isIPv6(e)){let t=re(e);if(!t)return!1;let r=re("::ffff:0:0");return ye(t,r,96)?Ae([...t.slice(12)].join(".")):ye(t,re("2000::"),3)?![["2001::",23],["2001:db8::",32],["2001:10::",28],["2001:2::",48],["2002::",16],["3fff::",20]].some(([o,s])=>ye(t,re(o),s)):!1}return!1}function fr(e){let t;try{t=new URL(String(e))}catch{return{ok:!1,error:`not a valid URL: ${String(e).slice(0,120)}`}}if(t.protocol!=="http:"&&t.protocol!=="https:")return{ok:!1,error:`refused protocol ${t.protocol} (only http/https)`};let r=t.hostname.toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,"");if(lr.has(r)||r.endsWith(".localhost")||r.endsWith(".internal"))return{ok:!1,error:`refused internal host ${r}`};let n=z.isIP(r);return n!==0&&!Ae(r)?{ok:!1,error:`refused private address ${r}`}:{ok:!0,url:t,host:r,isLiteralIp:n!==0}}async function xe(e,{lookupFn:t=ur.promises.lookup}={}){let r=fr(e);if(!r.ok)return r;if(r.isLiteralIp)return{ok:!0,url:r.url,addresses:[{address:r.host,family:z.isIPv6(r.host)?6:4}]};let n;try{n=await t(r.host,{all:!0,verbatim:!0})}catch{return{ok:!1,error:`refused: ${r.host} did not resolve`}}return!Array.isArray(n)||n.length===0||n.some(o=>!Ae(o.address))?{ok:!1,error:`refused: ${r.host} resolves to a non-public address`}:{ok:!0,url:r.url,addresses:n}}async function Se({requireUndici:e=!1,importUndici:t=()=>import("undici")}={}){let r,n;try{let c=await t();r=c.Agent,n=c.fetch}catch(c){if(e)throw new Error(`egress-guard: untrustedUrl pinning requires the undici package, which failed to load: ${c?.message||c}`);return null}if(typeof r!="function"||typeof n!="function"){if(e)throw new Error("egress-guard: untrustedUrl pinning requires undici's Agent and fetch exports, which were not found on the imported module");return null}let o=c=>String(c).toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,""),s=new Map,a=c=>(Array.isArray(c)?c:[c]).map(i=>typeof i=="string"?{address:i}:i).filter(i=>i&&i.address).map(i=>({address:i.address,family:i.family||(z.isIPv6(i.address)?6:4)})),u=(c,i,p)=>{s.set(o(c),a(typeof i=="string"?[{address:i,family:p}]:i))},l=c=>{let i=o(c);if(z.isIP(i))return[{address:i,family:z.isIPv6(i)?6:4}];let p=s.get(i);if(!p||!p.length)throw new Error(`refused: unpinned host ${c} during pinned fetch`);return p},f=new r({connect:{lookup(c,i,p){let m;try{m=l(c)}catch(y){return p(y)}return i?.all?p(null,m):p(null,m[0].address,m[0].family)}}}),d=dr((c,i={})=>n(c,{...i,dispatcher:f}),u);return{dispatcher:f,fetch:d,pin:u,resolve:l,async close(){try{await f.destroy()}catch{}}}}function dr(e,t){if(typeof e!="function")throw new Error("markPinCapableFetch: fetchImpl must be a function");if(typeof t!="function")throw new Error("markPinCapableFetch: pin must be a function");return e[_e]=Object.freeze({pin:t}),e}function Ie(e){return typeof e=="function"&&typeof e[_e]?.pin=="function"}function Ke(e,t,r){if(!Ie(e))throw new Error("pinFetchToAddresses: fetchImpl is not pin-capable");e[_e].pin(t,r)}var lr,_e,Ye=P(()=>{lr=new Set(["localhost","metadata.google.internal","metadata.goog"]);_e=Symbol.for("oracle.egressGuard.pinCapableFetch")});import{createHash as pr}from"node:crypto";function gr(e){let t=String(e||"").toLowerCase();return rt.includes(t)||/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(t)}function Er(e){let t={};for(let[r,n]of Object.entries(e||{}))gr(r)||(t[r]=n);return t}function yr(e,t){if(!e)throw new Error(`HTTP redirect from ${t} missing Location`);let r=new URL(String(e),String(t));if(r.protocol!=="http:"&&r.protocol!=="https:")throw new Error(`HTTP redirect from ${t} used unsupported protocol ${r.protocol}`);return r.toString()}function Ar(e,t){return new URL(String(e)).origin===new URL(String(t)).origin}function xr(e,t,r,n={}){let o={};for(let[d,c]of Object.entries(r||{}))o[d.toLowerCase()]=c;let s=Object.keys(o).filter(d=>/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(d)),u=[...new Set([...rt,...s])].sort().map(d=>`${d}=${o[d]??""}`).join(`
|
|
3
|
+
`),l=pr("sha256").update(u).digest("hex").slice(0,32),f=`${n.untrustedUrl?"untrusted":"trusted"}:${n.maxResponseBytes??"unbounded"}`;return`${e} ${t} ${f} ${l}`}function Sr(e,t){let r=Number(t);return Number.isFinite(r)&&r>0?Math.min(r*1e3,Ze):Math.min(250*2**e,Ze)+Math.floor(Math.random()*100)}function Y(e,t={}){let r=new Error(e);return r.retryable=!1,Object.assign(r,t),r}function Ne(e,t,r){return Y(`HTTP response from ${e} exceeded maxResponseBytes ${r} (${t})`,{oversize:!0})}function J(e){try{let t=e?.body?.cancel?.();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}function Ir(e){return e?e.byteLength??e.length??0:0}async function et(e,t,{url:r,truncate:n=!1,onOversize:o}={}){if(t==null)return await e.text();let s=Number(e.headers?.get?.("content-length"));if(Number.isFinite(s)&&s>t&&(J(e),!n))throw Ne(r,`content-length ${s}`,t);let a=e.body?.getReader?.();if(!a){let c=await e.text(),i=Buffer.byteLength(c,"utf8");if(i>t){if(!n)throw Ne(r,`body ${i} bytes`,t);return Buffer.from(c,"utf8").subarray(0,t).toString("utf8")}return c}let u=[],l=0,f=!1;try{for(;;){let{value:c,done:i}=await a.read();if(i)break;if(c&&(u.push(Buffer.from(c)),l+=Ir(c),l>t)){f=!0;break}}}finally{if(f)try{await a.cancel()}catch{}try{a.releaseLock?.()}catch{}}if(f&&(typeof o=="function"&&o(),!n))throw Ne(r,`streamed ${l} bytes`,t);let d=Buffer.concat(u);return(f?d.subarray(0,t):d).toString("utf8")}function tt(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function Cr(e,{fetchImpl:t,method:r,headers:n,body:o,timeoutMs:s,lookupFn:a,realFetch:u,untrustedUrl:l=!1,maxResponseBytes:f=null,importUndici:d,validateResponse:c}){let i=new AbortController,p=setTimeout(()=>i.abort(),s),m=null,y=t,S=a?{lookupFn:a}:{};if(l&&!u&&!Ie(y))throw Y(`HTTP refused ${e}: untrustedUrl requires a pin-capable fetchImpl (see markPinCapableFetch in egress-guard.mjs) or no fetchImpl override so Oracle can pin the connection itself`);let A=async(b,{status:E=null}={})=>{let g=await xe(b,S);if(!g.ok)throw Y(E==null?`HTTP refused ${b}: ${g.error}`:`HTTP redirect to ${b} ${g.error}`,E==null?{}:{status:E});let h=new URL(b).hostname;if(u){if(m&&(await m.close(),m=null),!m)try{m=await Se({requireUndici:!0,...d?{importUndici:d}:{}})}catch(w){throw Y(E==null?`HTTP refused ${b}: ${w?.message||w}`:`HTTP redirect to ${b} refused: ${w?.message||w}`,E==null?{}:{status:E})}m.pin(h,g.addresses),y=m.fetch}else Ke(y,h,g.addresses);return g};try{let b=String(e),E={...n||{}};l&&await A(b);for(let g=0;g<=Qe;g+=1){let h=await y(b,{method:r,headers:E,body:o,signal:i.signal,redirect:"manual"});if(br.has(h.status)){if(r!=="GET"&&r!=="HEAD"){let R=await et(h,f??wr,{url:b,truncate:!0}),T=new Error(`HTTP ${h.status} ${r} ${b} redirected non-idempotent request`);throw T.status=h.status,T.body=tt(R)??R.slice(0,300),T}if(g===Qe)throw J(h),new Error(`HTTP redirect loop for ${e}`);let x=h.headers?.get?.("location"),_;try{_=yr(x,b)}catch(R){throw J(h),R}let I=!Ar(_,b);if(J(h),I&&(E=Er(E)),l)await A(_,{status:h.status});else if(I){let R=await xe(_,S);if(!R.ok){let T=new Error(`HTTP redirect from ${b} ${R.error}`);throw T.status=h.status,T.retryable=!1,T}u&&R.addresses?.length&&(m||(m=await Se(d?{importUndici:d}:{})),m&&(m.pin(new URL(_).hostname,R.addresses),y=m.fetch))}b=_;continue}if(typeof c=="function")try{await c(h,{url:b})}catch(x){throw J(h),Y(x?.message||String(x))}let w=await et(h,f,{url:b,onOversize:()=>i.abort()}),N=tt(w);if(!h.ok){let x=new Error(`HTTP ${h.status} ${r} ${b}`);throw x.status=h.status,x.retryAfter=h.headers?.get?.("retry-after")??null,x.body=N??w.slice(0,300),x}return N??w}throw new Error(`HTTP redirect loop for ${e}`)}finally{clearTimeout(p),m&&await m.close()}}async function ne(e,t={}){let r=t.fetchImpl||globalThis.fetch;if(typeof r!="function")throw new Error("fetch unavailable \u2014 pass opts.fetchImpl");let n=t.timeoutMs??12e3,o=(t.method||"GET").toUpperCase(),s={Accept:"application/json",...t.headers||{}},a=t.body;a!=null&&typeof a!="string"&&(s["Content-Type"]=s["Content-Type"]||"application/json",a=JSON.stringify(a));let u=Number.isInteger(t.retries)?Math.max(t.retries,0):hr,l=t.lookupFn,f=!t.fetchImpl,d=t.untrustedUrl===!0,c=t.importUndici,i=t.validateResponse,p=Number(t.maxResponseBytes),m=Number.isFinite(p)&&p>0?Math.floor(p):null,y=async()=>{let g;for(let h=0;h<=u;h++)try{return await Cr(e,{fetchImpl:r,method:o,headers:s,body:a,timeoutMs:n,lookupFn:l,realFetch:f,untrustedUrl:d,maxResponseBytes:m,importUndici:c,validateResponse:i})}catch(w){g=w;let N=w?.status,x=w?.name==="AbortError",_=new Set([408,425,429]),I=w?.retryable===!1?!1:N!=null?_.has(N)||mr.has(N)&&Je.has(o):!x&&Je.has(o);if(h===u||!I)throw w;await _r(Sr(h,w?.retryAfter))}throw g};if(!(t.dedupe!==!1&&o==="GET"&&a==null))return y();let A=xr(o,e,s,{untrustedUrl:d,maxResponseBytes:m}),b=Ce.get(A);if(b)return b;let E=y().finally(()=>Ce.delete(A));return Ce.set(A,E),E}var mr,Je,hr,Ze,rt,br,Qe,wr,Ce,_r,Oe=P(()=>{Ye();mr=new Set([408,425,429,500,502,503,504]),Je=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),hr=2,Ze=4e3,rt=["authorization","x-api-key","x-tensor-api-key","0x-api-key","api-key","cookie","proxy-authorization"],br=new Set([301,302,303,307,308]),Qe=3,wr=64*1024;Ce=new Map;_r=e=>new Promise(t=>setTimeout(t,e))});function Te(e){return nt.get(Number(e))||null}function ot(e,t=process.env){let r=Te(e);if(!r)return null;for(let n of r.rpcEnv){let o=(t[n]||"").trim();if(o)return o}return null}function st(e){return nt.has(Number(e))}var Re,nt,it=P(()=>{Re={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}},nt=new Map(Object.values(Re).map(e=>[e.chainId,e]))});var ct={};Xe(ct,{PUBLIC_RPC_FALLBACKS:()=>Be,erc20Allowance:()=>Lr,erc20BalanceOf:()=>Dr,resolveRpcUrl:()=>$e,rpcBlockNumber:()=>Pe,rpcCall:()=>O,rpcChainId:()=>Br,rpcGasPrice:()=>$r,rpcGetBalance:()=>Pr,rpcHealth:()=>at,rpcHealthAll:()=>Mr,transactionReceipt:()=>vr});import{Interface as Nr,getAddress as Or}from"ethers";function U(e,t){try{return Or(e).toLowerCase()}catch{throw new Error(`${t} must be a valid EVM address`)}}function Rr(e){let t=String(e||"").trim();if(!/^0x[0-9a-fA-F]{64}$/.test(t))throw new Error("txHash must be a 32-byte hex transaction hash");return t.toLowerCase()}function ke(e){return e==null?null:Number.parseInt(String(e),16)}function $e(e,{rpcUrl:t,env:r=process.env}={}){if(t)return t;let n=ot(e,r);return n||Be[Number(e)]||null}function kr(e){let t=String(e||""),r=t.toLowerCase();if(t!==t.trim()||!/^[a-zA-Z0-9_]+$/.test(t)||!Tr.test(r))throw new Error(`evm-rpc: ${t} refused \u2014 @oracle-agent/oracle is prepare-only (read RPC only; no broadcast/sign)`);return r}async function O(e,t,r=[],n={}){let o=String(t||"");kr(o);let s=$e(e,n);if(!s)throw new Error(`No RPC URL for chainId ${e} (set env from chain registry rpcEnv or pass rpcUrl)`);let u=await ne(s,{method:"POST",body:{jsonrpc:"2.0",id:1,method:t,params:r},fetchImpl:n.fetchImpl,timeoutMs:n.timeoutMs??12e3});if(u?.error){let l=new Error(u.error.message||JSON.stringify(u.error));throw l.code=u.error.code,l}return u.result}async function at(e,t={}){let r=await O(e,"eth_blockNumber",[],t),n=parseInt(r,16),o=await O(e,"eth_chainId",[],t),s=parseInt(o,16);return{ok:Number.isFinite(n)&&s===Number(e),chainId:Number(e),reportedChainId:s,blockNumber:n,name:Te(e)?.name||null}}async function Pe(e,t={}){let r=await O(e,"eth_blockNumber",[],t);return parseInt(r,16)}async function Br(e,t={}){let r=await O(e,"eth_chainId",[],t);return parseInt(r,16)}async function $r(e,t={}){let r=await O(e,"eth_gasPrice",[],t);if(r==null)return null;try{return BigInt(r)}catch{return null}}async function Pr(e,t,r={}){if(!t)throw new Error("rpcGetBalance requires address");let n=await O(e,"eth_getBalance",[t,"latest"],r);return{chainId:Number(e),address:t,balanceWei:BigInt(n).toString(),balanceHex:n}}async function Lr(e={},t={}){let r=Number(e.chainId??t.chainId??1),n=U(e.token||e.tokenAddress,"token"),o=U(e.owner,"owner"),s=U(e.spender,"spender"),a=oe.encodeFunctionData("allowance",[o,s]),u=await O(r,"eth_call",[{to:n,data:a},e.blockTag||"latest"],t),l=oe.decodeFunctionResult("allowance",u),f=BigInt(l[0]);return{chainId:r,token:n,owner:o,spender:s,allowance:f.toString(),allowanceHex:`0x${f.toString(16)}`,blockTag:e.blockTag||"latest"}}async function Dr(e={},t={}){let r=Number(e.chainId??t.chainId??1),n=U(e.token||e.tokenAddress,"token"),o=U(e.account||e.owner||e.address,"account"),s=oe.encodeFunctionData("balanceOf",[o]),a=await O(r,"eth_call",[{to:n,data:s},e.blockTag||"latest"],t),u=oe.decodeFunctionResult("balanceOf",a),l=BigInt(u[0]);return{chainId:r,token:n,account:o,balance:l.toString(),balanceHex:`0x${l.toString(16)}`,blockTag:e.blockTag||"latest"}}async function vr(e={},t={}){let r=Number(e.chainId??t.chainId??1),n=Rr(e.txHash||e.hash||e.transactionHash),o=await O(r,"eth_getTransactionReceipt",[n],t);if(!o)return{ok:!1,chainId:r,txHash:n,status:"pending",receipt:null,reason:"receipt pending"};let s=ke(o.status),a=s===1,u=s===1?"success":s===0?"reverted":"unknown",l=a?null:u==="reverted"?"transaction reverted":"unknown receipt status",f=e.expectedTo?U(e.expectedTo,"expectedTo"):null,d=o.to?U(o.to,"receipt.to"):null;return f&&d!==f&&(a=!1,l=`to mismatch: expected ${f}, got ${d||"null"}`),{ok:a,chainId:r,txHash:n,status:u,reason:l,statusCode:s,to:d,from:o.from?U(o.from,"receipt.from"):null,blockNumber:ke(o.blockNumber),transactionIndex:ke(o.transactionIndex),logs:Array.isArray(o.logs)?o.logs:[],receipt:o}}async function Mr(e={}){let t=e.chainIds||Object.values(Re).map(n=>n.chainId),r={};return await Promise.all(t.map(async n=>{if(!st(n)&&!Be[n]&&!$e(n,e)){r[n]={ok:!1,error:"no rpc configured",chainId:n};return}try{r[n]=await at(n,e)}catch(o){r[n]={ok:!1,chainId:n,error:String(o.message||o)}}})),r}var oe,Be,Tr,se=P(()=>{Oe();it();oe=new Nr(["function allowance(address owner,address spender) view returns (uint256)","function balanceOf(address account) view returns (uint256)"]);Be={1:"https://ethereum.publicnode.com",137:"https://polygon-bor-rpc.publicnode.com",42161:"https://arbitrum-one-rpc.publicnode.com",8453:"https://base-rpc.publicnode.com",10:"https://optimism-rpc.publicnode.com",988:"https://rpc.stable.xyz",56:"https://bsc-rpc.publicnode.com",43114:"https://avalanche-c-chain-rpc.publicnode.com",999:"https://rpc.hyperliquid.xyz/evm",2741:"https://api.mainnet.abs.xyz",4663:"https://rpc.mainnet.chain.robinhood.com"};Tr=/^(?:eth_(?:call|blocknumber|chainid|get[a-z0-9]+|feehistory|gasprice|maxpriorityfeepergas|syncing|protocolversion|estimategas|createaccesslist)|net_(?:version|listening|peercount)|web3_(?:clientversion|sha3))$/});function dn(e,t,r){let n=L(t),o=L(r),s=L(e?.baseToken?.address),a=L(e?.quoteToken?.address);return s===n&&a===o||s===o&&a===n}function pn(e){let t=Number(e?.liquidity?.usd);return Number.isFinite(t)&&t>=0?t:null}function mn(e={}){return(e.baseUrl||process.env.DEXSCREENER_API_URL||un).replace(/\/$/,"")}async function hn(e,t={}){if(!e)throw new Error("tokenAddress required");return ne(`${mn(t)}/latest/dex/tokens/${e}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??12e3})}async function It({chainId:e,tokenA:t,tokenB:r,dexIds:n=[]}={},o={}){if(e==null||!t||!r)throw new Error("chainId, tokenA, and tokenB required");let s=L(ln[Number(e)]||e),a=new Set(fn(n).filter(Boolean).map(L)),u=[...new Set([t,r].map(i=>String(i)).filter(Boolean))],l=await Promise.allSettled(u.map(i=>hn(i,{...o,baseUrl:o.dexscreenerBaseUrl,timeoutMs:o.dexscreenerTimeoutMs??Math.min(Number(o.timeoutMs??4e3),4e3)}))),f=new Set,d=[];for(let i of l)if(i.status==="fulfilled")for(let p of i.value?.pairs||i.value?.data?.pairs||[]){let m=`${L(p?.chainId)}:${L(p?.dexId)}:${L(p?.pairAddress)}`;f.has(m)||(f.add(m),d.push(p))}return d.filter(i=>L(i?.chainId)===s).filter(i=>dn(i,t,r)).filter(i=>!a.size||a.has(L(i?.dexId))).map(i=>({pairAddress:i.pairAddress??null,dexId:i.dexId??null,chainId:i.chainId??null,liquidityUsd:pn(i),pairCreatedAt:i.pairCreatedAt??null})).filter(i=>i.liquidityUsd!=null).sort((i,p)=>p.liquidityUsd-i.liquidityUsd)}var un,ln,L,fn,Ct=P(()=>{Oe();un="https://api.dexscreener.com",ln=Object.freeze({1:"ethereum",10:"optimism",56:"bsc",137:"polygon",8453:"base",42161:"arbitrum",43114:"avalanche",999:"hyperevm",4663:"robinhood"}),L=e=>String(e??"").toLowerCase(),fn=e=>Array.isArray(e)?e:e==null?[]:[e]});import{readFileSync as bn}from"node:fs";import{homedir as wn}from"node:os";import{join as ue}from"node:path";function gn(){if(process.env.ORACLE_TEST_ISOLATE_SECRETS==="1"){let r=(process.env.ORACLE_EXEC_ENV_FILE||"").trim();return r?[r]:[]}let e=(process.env.ORACLE_EXEC_ENV_FILE||process.env.MAD_EXEC_ENV_FILE||"").trim(),t=wn();if(process.env.ORACLE_PUBLIC_DESKTOP==="1"){let r=(process.env.ORACLE_CONFIG_DIR||ue(t,".config","oracle")).trim();return[e,ue(r,"exec.env")].filter(Boolean)}return[e,ue(t,".config","oracle","exec.env"),ue(t,".config","mad-desk","exec.env")].filter(Boolean)}function Nt(e,t,r){let n=e??process.env[t]??process.env[r];if(!String(n||"").trim())for(let o of gn())try{let s=bn(o,"utf8"),a=s.match(new RegExp(`^${t}=(.*)$`,"m"))||s.match(new RegExp(`^${r}=(.*)$`,"m"));if(a&&(n=a[1].trim(),n))break}catch{}if(!String(n||"").trim())throw new Error(`${t} required for attestation. Set it in the environment, or place ${t}=<value> in ~/.config/oracle/exec.env`);return n}var Ot=P(()=>{});var Rt=P(()=>{});import{createHash as $o,createHmac as En,timingSafeEqual as Po}from"node:crypto";function We(e){return Array.isArray(e)?`[${e.map(We).join(",")}]`:e&&typeof e=="object"?`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${We(e[t])}`).join(",")}}`:JSON.stringify(e??null)}function yn(e,{required:t=!1}={}){try{return Nt(e,"ORACLE_ROUTE_ATTESTATION_SECRET","MAD_ROUTE_ATTESTATION_SECRET")}catch(r){if(t)throw r;return null}}function An(e){let{signature:t,...r}=e;return r}function xn(e,{secret:t}={}){let r=yn(t);return r?{...e,signature:En("sha256",r).update(We(An(e))).digest("hex")}:e}function Ue(e,t=0){let r=Number(e);return Number.isFinite(r)?r:t}function Sn(e){let t=e==null?Tt:Number(e);if(!Number.isInteger(t)||t<0)throw new Error("auto-slippage cap must be a non-negative integer bps value");return Math.min(t,Tt)}function _n({liquidityUsd:e,priceChange5m:t=0,quoteAgeMs:r=0,crossChain:n=!1,requestedCapBps:o}={}){let s=Ue(e,0),a=s>0?s>=25e4?5:s>=1e5?10:s>=5e4?20:s>=1e4?40:70:n?30:10,u=Math.min(60,Math.abs(Ue(t,0))*2),l=Math.min(40,Math.floor(Math.max(0,Ue(r,0))/5e3)*5),f=Math.max(25,Math.ceil(20+a+u+l)),d=Sn(o);return{mode:"auto",requiredBps:f,selectedBps:Math.min(f,d),capBps:d,executable:f<=d}}function In({chainId:e,venue:t,quoteAmountOut:r,liquidityUsd:n,priceChange5m:o=0,quoteAgeMs:s=0,crossChain:a=!1,requestedCapBps:u,quotedAtMs:l=Date.now(),ttlMs:f=kt,secret:d}={}){let c=BigInt(r??0);if(c<=0n)throw new Error("auto-slippage guard requires positive quoteAmountOut");let i=_n({liquidityUsd:n,priceChange5m:o,quoteAgeMs:s,crossChain:a,requestedCapBps:u});if(!i.executable)throw new Error(`auto-slippage requires ${i.requiredBps} bps above hard/requested cap ${i.capBps}; route blocked`);let p=Number(l);if(!Number.isFinite(p))throw new Error("auto-slippage: quotedAtMs must be a finite number");let m=Math.min(3e4,Math.max(1e3,Number(f)||kt)),y=c*BigInt(1e4-i.selectedBps),S=y/10000n;if(y%10000n!==0n&&(S+=1n),S>c&&(S=c),c>0n&&S<=0n)throw new Error(`auto-slippage: quote ${c} is too small to express a ${i.selectedBps} bps floor without rounding to zero`);let A=Number((c-S)*10000n/(c===0n?1n:c));if(A>i.capBps)throw new Error(`auto-slippage: realised floor implies ${A} bps, above cap ${i.capBps} \u2014 refusing to issue a guard weaker than advertised`);return xn({mode:"auto",chainId:Number(e),venue:String(t||"unknown"),quoteAmountOut:c.toString(),minAmountOut:S.toString(),requiredBps:i.requiredBps,selectedBps:i.selectedBps,capBps:i.capBps,quotedAtMs:p,expiresAtMs:p+m},{secret:d})}function Bt(e,{chainId:t,venue:r,amountOut:n,liquidityUsd:o,priceChange5m:s,crossChain:a,requestedCapBps:u,quotedAtMs:l=Date.now(),ttlMs:f}={}){let d=In({chainId:t,venue:r,quoteAmountOut:n,liquidityUsd:o,priceChange5m:s,crossChain:a,requestedCapBps:u,quotedAtMs:l,ttlMs:f});return{...e,autoSlippage:d,amountOutMinimum:d.minAmountOut}}var Tt,kt,$t=P(()=>{Ot();Rt();Tt=100,kt=2e4});var Mo,Fo,Pt=P(()=>{Mo=300*1e3,Fo=(()=>{let e=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(e)&&e>0?e:1800*1e3})()});import{Interface as vt,getAddress as le,isAddress as Mt}from"ethers";function kn(e,t){let r=Number(e),n=ee[r];if(!n)throw new Error(`uniswap-v3: unsupported chainId ${e} (supported: ${Object.keys(ee).join(", ")})`);let o=Tn[r]||{};if(!t){if(!n.quoter||!n.router){let l=Object.keys(o).join(", ")||"none registered";throw new Error(`uniswap-v3: chain ${r} (${n.name}) has no canonical Uniswap v3 deployment -- name a venue explicitly (known: ${l})`)}return{chainId:r,venue:n.name,...n}}let s=String(t).toLowerCase();if(s===n.name&&n.quoter&&n.router)return{chainId:r,venue:n.name,...n};let a=o,u=a[s];if(!u){let l=[...n.quoter&&n.router?[n.name]:[],...Object.keys(a)].join(", ");throw new Error(`uniswap-v3: unknown venue "${t}" on chain ${r} (known: ${l})`)}return{chainId:r,venue:s,...n,quoter:u.quoter,router:u.router,feeTiers:u.feeTiers||null}}function Dt(e,t){let r=ee[Number(t)];if(!e||e===On||e===Rn||/^eth$/i.test(String(e)))return le(r.weth);let n=String(e);if(/^weth$/i.test(n))return le(r.weth);if(/^usdc$/i.test(n))return le(r.usdc);if(!Mt(n))throw new Error(`invalid token address: ${e}`);return le(n)}function Bn(e){let t=String(e||"uniswap").toLowerCase();return t==="uniswap"?["uniswap-v3","uniswap"]:t==="pancakeswap"?["pancakeswap-v3","pancakeswap"]:t==="hyperswap"?["hyperswap-v3","hyperswap"]:[t,`${t}-v3`]}async function Ft(e={},t={}){let{chainId:r,quoter:n,router:o,feeTiers:s}=kn(e.chainId??8453,e.venue),a=Dt(e.tokenIn||"WETH",r),u=Dt(e.tokenOut||ee[r].usdc,r),l=BigInt(e.amountIn??0);if(l<=0n)throw new Error("amountIn required (raw base units)");let f=s&&s.length?s:Cn,d=e.fee!=null?[Number(e.fee)]:e.tryFees===!1?[f[Math.min(2,f.length-1)]]:[...f],c=[],i=null;for(let w of d){let N=Lt.encodeFunctionData("quoteExactInputSingle",[{tokenIn:a,tokenOut:u,amountIn:l,fee:w,sqrtPriceLimitX96:0n}]);try{let x=await O(r,"eth_call",[{to:n,data:N},"latest"],t);if(!x||x==="0x"){c.push({fee:w,ok:!1,error:"empty result"});continue}let _=Lt.decodeFunctionResult("quoteExactInputSingle",x),I={fee:w,ok:!0,amountOut:_[0].toString(),sqrtPriceX96After:_[1].toString(),initializedTicksCrossed:Number(_[2]),gasEstimate:_[3].toString()};c.push(I),(!i||BigInt(I.amountOut)>BigInt(i.amountOut))&&(i=I)}catch(x){c.push({fee:w,ok:!1,error:String(x.message||x).slice(0,160)})}}if(!i){let w=c.map(N=>`${N.fee}:${N.error||"fail"}`).join("; ");throw new Error(`uniswap-v3 quote failed chain=${r}: ${w}`)}let p=e.liquidityUsd==null?await It({chainId:r,tokenA:a,tokenB:u,dexIds:Bn(e.venue)},t).catch(()=>[]):[],m={};for(let w of p.slice(0,8))if(!(!w.pairAddress||!Mt(w.pairAddress)))try{let N=await O(r,"eth_call",[{to:w.pairAddress,data:Nn},"latest"],t),x=N&&N!=="0x"&&N.length<=66?Number.parseInt(N,16):NaN;if(!Number.isFinite(x)||x<=0||x>1e6)continue;(m[x]==null||w.liquidityUsd>m[x].liquidityUsd)&&(m[x]=w)}catch{}let y=e.liquidityBandBps==null?50:Number(e.liquidityBandBps),S=null;if(e.fee==null&&y>0&&BigInt(i.amountOut)>0n){let w=BigInt(i.amountOut),x=c.filter(_=>_.ok&&Number((w-BigInt(_.amountOut))*10000n/w)<=y).filter(_=>m[_.fee]?.liquidityUsd!=null).sort((_,I)=>m[I.fee].liquidityUsd-m[_.fee].liquidityUsd)[0];x&&x.fee!==i.fee&&(S={priceBestFee:i.fee,chosenFee:x.fee,chosenPoolUsd:m[x.fee].liquidityUsd,bandBps:y},i=x)}let A=m[i.fee]??null,b=p[0]??null,E=A??b,g=e.liquidityUsd??A?.liquidityUsd??b?.liquidityUsd??null,h=e.liquidityUsd!=null?"caller":A?"pool":b?"pair":null;return Bt({venue:"uniswap-v3",chainId:r,chain:ee[r].name,quoter:n,tokenIn:a,tokenOut:u,amountIn:l.toString(),fee:i.fee,amountOut:i.amountOut,gasEstimate:i.gasEstimate,liquidityUsd:g,liquiditySource:E,liquidityAttribution:h,liquidityPick:S,sqrtPriceX96After:i.sqrtPriceX96After,initializedTicksCrossed:i.initializedTicksCrossed,triedFees:c,best:!0},{chainId:r,venue:o,amountOut:i.amountOut,liquidityUsd:g,priceChange5m:e.priceChange5m,requestedCapBps:e.maxSlippageBps??e.slippageBps})}var ee,Cn,Nn,Lt,Xo,On,Rn,He,Tn,Ut=P(()=>{se();Ct();$t();Pt();ee={1:{name:"ethereum",quoter:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",router:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",weth:"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",usdc:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},8453:{name:"base",quoter:"0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a",router:"0x2626664c2603336E57B271c5C0b26F421741e481",weth:"0x4200000000000000000000000000000000000006",usdc:"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"},42161:{name:"arbitrum",quoter:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",router:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",weth:"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",usdc:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831"},4663:{name:"robinhood",quoter:"0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7",router:"0xcaf681a66d020601342297493863e78c959e5cb2",weth:"0x0bd7d308f8e1639fab988df18a8011f41eacad73",usdc:"0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168"},999:{name:"hyperevm",weth:"0x5555555555555555555555555555555555555555",usdc:"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb"},10:{name:"optimism",quoter:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",router:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",weth:"0x4200000000000000000000000000000000000006",usdc:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"},56:{name:"bsc",quoter:"0x78D78E420Da98ad378D7799bE8f4AF69033EB077",router:"0xB971eF87ede563556b2ED4b1C0b0019111Dd85d2",weth:"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",usdc:"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d"},137:{name:"polygon",quoter:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",router:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",weth:"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",usdc:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"},43114:{name:"avalanche",quoter:"0xbe0F5544EC67e9B3b2D979aaA43f18Fd87E6257F",router:"0xbb00FF08d01D300023C629E8fFfFcb65A5a578cE",weth:"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",usdc:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"}},Cn=[100,500,3e3,1e4],Nn="0xddca3f43",Lt=new vt(["function quoteExactInputSingle((address tokenIn, address tokenOut, uint256 amountIn, uint24 fee, uint160 sqrtPriceLimitX96) params) returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)","function quoteExactInput(bytes path, uint256 amountIn) returns (uint256 amountOut, uint160[] sqrtPriceX96AfterList, uint32[] initializedTicksCrossedList, uint256 gasEstimate)"]),Xo=new vt(["function exactInputSingle((address tokenIn,address tokenOut,uint24 fee,address recipient,uint256 amountIn,uint256 amountOutMinimum,uint160 sqrtPriceLimitX96) params) payable returns (uint256 amountOut)","function multicall(uint256 deadline,bytes[] data) payable returns (bytes[] results)"]),On="0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",Rn="0x0000000000000000000000000000000000000000",He=[100,500,2500,1e4],Tn={56:{pancakeswap:{name:"pancakeswap",quoter:"0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997",router:"0x13f4EA83D0bd40E75C8222255bc855a974568Dd4",feeTiers:He}},8453:{pancakeswap:{name:"pancakeswap",quoter:"0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997",router:"0x13f4EA83D0bd40E75C8222255bc855a974568Dd4",feeTiers:He}},42161:{pancakeswap:{name:"pancakeswap",quoter:"0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997",router:"0x13f4EA83D0bd40E75C8222255bc855a974568Dd4",feeTiers:He}},999:{hyperswap:{name:"hyperswap",quoter:"0x03A918028f22D9E1473B7959C927AD7425A45C7C",router:"0x4E2960a8cd19B467b82d26D83fAcb0fAE26b094D"}}}});var Gt={};Xe(Gt,{ARB_UNI_FEE_TIERS:()=>zt,collectArbRoundTripCycles:()=>Dn});function qe(e,{positive:t=!1}={}){return typeof e=="string"&&/^(?:0|[1-9][0-9]*)$/.test(e)&&(!t||e!=="0")&&BigInt(e)<=$n}function Wt(e){if(!qe(e,{positive:!0})){let t=typeof e=="string"&&/^[1-9][0-9]*$/.test(e)?" and fit uint256":"";throw new TypeError(`amountInWei must be a positive strict decimal string${t}`)}return e}function Ht(e,t){let r=e?.amountOut;if(!qe(r,{positive:!0}))throw new Error(`${t} returned an invalid amountOut`);return r}function qt(e,t){let r=e?.gasEstimate??e?.gasUnits;if(!qe(r))throw new Error(`${t} returned invalid gas units`);return r}function fe(e,t,r,n,o,s){return{status:"UNAVAILABLE",entryVenue:e,exitVenue:t,amountInWei:r,intermediateAmountBase:n,amountOutWei:null,gasUnits:null,source:o,error:String(s?.message||s)}}function jt(e){return`uniswap-v3-${e}`}async function Pn({entryFee:e,exitFee:t,amountInWei:r,blockTag:n,quoteUniswap:o}){let s=jt(e),a=jt(t),u;try{u=await o({chainId:te,tokenIn:"WETH",tokenOut:"USDC",amountIn:r,fee:e,tryFees:!1,blockTag:n})}catch(c){return fe(s,a,r,null,{},c)}let l,f;try{l=Ht(u,s),f=qt(u,s)}catch(c){return fe(s,a,r,null,{entry:{venue:"uniswap-v3",fee:e}},c)}let d;try{d=await o({chainId:te,tokenIn:"USDC",tokenOut:"WETH",amountIn:l,fee:t,tryFees:!1,blockTag:n})}catch(c){return fe(s,a,r,l,{entry:{venue:"uniswap-v3",fee:e}},c)}try{let c=Ht(d,a),i=(BigInt(f)+BigInt(qt(d,a))).toString();return{status:"OK",entryVenue:s,exitVenue:a,amountInWei:r,intermediateAmountBase:l,amountOutWei:c,gasUnits:i,source:{entry:{venue:"uniswap-v3",fee:e},exit:{venue:"uniswap-v3",fee:t}}}}catch(c){return fe(s,a,r,l,{entry:{venue:"uniswap-v3",fee:e},exit:{venue:"uniswap-v3",fee:t}},c)}}async function Ln(e){let t=await O(te,"eth_gasPrice",[],e);return BigInt(t).toString()}async function Dn(e={}){let t=Wt(e.amountInWei),r=e.quoteUniswap??(y=>Ft(y,e)),n=e.getBlockNumber??(()=>Pe(te,e)),o=e.getGasPriceWei??(()=>Ln(e)),s=e.now??(()=>new Date().toISOString()),a=e.maxBlockDrift??1,u=Array.isArray(e.feeTiers)&&e.feeTiers.length?e.feeTiers.map(Number):[...zt];if(!Number.isSafeInteger(a)||a<0)throw new TypeError("maxBlockDrift must be a non-negative safe integer");for(let y of u)if(![100,500,3e3,1e4].includes(y))throw new TypeError(`unsupported Uni fee tier: ${y}`);let l=e.pinnedBlock??await n();if(!Number.isSafeInteger(l)||l<0)throw new Error("block provider returned invalid height");let f=`0x${l.toString(16)}`,d=Wt(await o()),c=[];for(let y of u)for(let S of u)y!==S&&c.push({entryFee:y,exitFee:S});let i=await Promise.all(c.map(({entryFee:y,exitFee:S})=>Pn({entryFee:y,exitFee:S,amountInWei:t,blockTag:f,quoteUniswap:r}))),p=await n();if(!Number.isSafeInteger(p)||p<0)throw new Error("block provider returned invalid height");let m=Math.abs(p-l);return{mode:"shadow",executionReady:!1,chainId:te,pair:"WETH-USDC",capturedAt:s(),amountInWei:t,blockStart:l,blockEnd:p,pinnedBlock:l,blockTag:f,blockConsistency:"PINNED",blockDrift:m,maxBlockDrift:a,stale:m>a,gasPriceWei:d,cycles:i,venueNote:"uniswap-v3-fee-tiers-only; camelot/pancake deferred"}}var te,$n,zt,Vt=P(()=>{se();Ut();te=42161,$n=(1n<<256n)-1n,zt=Object.freeze([100,500,3e3])});import{homedir as Zn}from"node:os";import{isAbsolute as Qn,join as eo}from"node:path";var Le=Object.freeze({premium:"0x074b2e43",provider:"0x0542975c",reserves:"0xd1946dbc"}),lt=/^0x[0-9a-fA-F]{64}$/,Fr=/^0x(?:0|[1-9a-fA-F][0-9a-fA-F]*)$/,Ur=256,Wr=100;async function Hr(...e){let{rpcCall:t}=await Promise.resolve().then(()=>(se(),ct));return t(...e)}function De(e){if(e&&typeof e=="object"&&!Object.isFrozen(e)){for(let t of Object.values(e))De(t);Object.freeze(e)}return e}var v=De({chainId:42161,pool:"0x794a61358D6845594F94dc1DB02A252b5b4814aD",addressesProvider:"0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb",WETH:"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",USDC:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",requiredReserves:["0x82aF49447D8a07e3bd95BD0d56f35241523fBab1","0xaf88d065e77c8cC2239327C5EDb3A432268e5831"],observedPremiumBps:5});function qr(e){if(typeof e!="string"||!Fr.test(e))throw new Error("malformed eth_blockNumber result");let t=BigInt(e);if(t>BigInt(Number.MAX_SAFE_INTEGER))throw new Error("malformed eth_blockNumber result: outside safe range");return Number(t)}function jr(e,t){if(typeof e!="string"||!lt.test(e))throw new Error(`malformed ${t} result`);return BigInt(e)}function ft(e,t){if(typeof e!="string"||!lt.test(e)||e.slice(2,26)!=="0".repeat(24))throw new Error(`malformed ${t} result`);return`0x${e.slice(26).toLowerCase()}`}function zr(e){if(typeof e!="string"||!/^0x[0-9a-fA-F]+$/.test(e)||e.length<130)throw new Error("malformed getReservesList result");let t=e.slice(2);if(t.length%64!==0||BigInt(`0x${t.slice(0,64)}`)!==32n)throw new Error("malformed getReservesList result");let r=BigInt(`0x${t.slice(64,128)}`);if(r>BigInt(Ur)||r>BigInt(Number.MAX_SAFE_INTEGER))throw new Error("malformed getReservesList result: unreasonable reserve count");let n=Number(r);if(t.length!==128+n*64)throw new Error("malformed getReservesList result: invalid length");let o=[];for(let s=0;s<n;s+=1){let a=`0x${t.slice(128+s*64,192+s*64)}`;o.push(ft(a,"getReservesList address"))}return o}function ut(e,t,r,n){return De({mode:"shadow",executionReady:!1,status:e,chainId:v.chainId,block:t,premiumBps:r,reasons:n})}async function dt(e={}){let t=e.rpc??Hr;if(typeof t!="function")throw new TypeError("rpc must be a function");let r=null,n=null;try{let o=await t(v.chainId,"eth_blockNumber",[],e);r=qr(o);let s=c=>t(v.chainId,"eth_call",[{to:v.pool,data:c},o],e),a=jr(await s(Le.premium),"FLASHLOAN_PREMIUM_TOTAL");if(a>BigInt(Number.MAX_SAFE_INTEGER))throw new Error("malformed FLASHLOAN_PREMIUM_TOTAL result: outside safe range");n=Number(a);let u=ft(await s(Le.provider),"ADDRESSES_PROVIDER"),l=zr(await s(Le.reserves)),f=[];n>Wr?f.push(`premium ${n} bps exceeds reasonable bound`):n!==v.observedPremiumBps&&f.push(`premium ${n} bps differs from observed ${v.observedPremiumBps} bps`),u!==v.addressesProvider.toLowerCase()&&f.push(`addresses provider mismatch: received ${u}`);let d=new Set(l);for(let[c,i]of[["WETH",v.WETH],["USDC",v.USDC]])d.has(i.toLowerCase())||f.push(`${c} required reserve is missing`);return ut(f.length===0?"AVAILABLE":"MISMATCH",r,n,f)}catch(o){return ut("UNAVAILABLE",r,n,[String(o?.message||o)])}}var Gr=/^(?:0|[1-9][0-9]*)$/,pt=10000n,ve=(1n<<256n)-1n;function k(e,t="value"){let r;if(typeof e=="bigint"&&e>=0n)r=e;else if(typeof e=="string"&&Gr.test(e))r=BigInt(e);else throw new TypeError(`${t} must be a non-negative plain decimal string or bigint`);if(r>ve)throw new RangeError(`${t} must fit uint256`);return r}function ie(e,t){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=0?BigInt(e):k(e,t)}function Vr(e,t){let r=k(e,"amount"),n=ie(t,"basisPoints");if(n>pt)throw new RangeError("basisPoints must be at most 10000");let o=r*n;return o===0n?0n:(o-1n)/pt+1n}function Z(e){if(typeof e!="bigint")throw new TypeError("value must be a bigint");return e.toString(10)}function mt(e,t){if(e===null||typeof e!="object"||Array.isArray(e))throw new TypeError(`${t} must be an object`);return e}function ht(e){for(let t of Object.values(e))t!==null&&typeof t=="object"&&!Object.isFrozen(t)&&ht(t);return Object.freeze(e)}function bt(e,t){mt(e,"cycle"),mt(t,"policy");let r=k(e.amountInWei,"cycle.amountInWei"),n=k(e.amountOutWei,"cycle.amountOutWei"),o=ie(e.gasUnits,"cycle.gasUnits"),s=k(e.gasPriceWei,"cycle.gasPriceWei"),a=ie(t.loanPremiumBps,"policy.loanPremiumBps"),u=k(t.builderFeeWei,"policy.builderFeeWei"),l=k(t.extraCostWei,"policy.extraCostWei"),f=k(t.minProfitWei,"policy.minProfitWei"),d=k(t.maxGasWei,"policy.maxGasWei"),c=k(t.maxLoanWei,"policy.maxLoanWei");ie(t.maxBlockDrift,"policy.maxBlockDrift");let i=n-r,p=o*s;if(p>ve)throw new RangeError("gas cost must fit uint256");let m=Vr(r,a),y=p+m+u+l;if(y>ve)throw new RangeError("total cost must fit uint256");let S=i-y,A=S>=f&&p<=d&&r<=c;return ht({grossProfitWei:Z(i),gasCostWei:Z(p),loanPremiumWei:Z(m),totalCostWei:Z(y),netProfitWei:Z(S),status:A?"PROFITABLE":"UNPROFITABLE",executionReady:!1,mode:"shadow"})}var Xr=/^(?:0|[1-9][0-9]*)$/,Kr=(1n<<256n)-1n;function Q(e){let t=null;return typeof e=="bigint"&&e>=0n&&(t=e),typeof e=="string"&&Xr.test(e)&&(t=BigInt(e)),t!==null&&t<=Kr?t:null}function ae(e){return typeof e=="string"&&e.length>0?e:null}function Me(e){return Array.isArray(e)&&e.every(t=>typeof t=="string")?e:null}function B(e,t){e.push(`MALFORMED_${t.replaceAll(/[^A-Za-z0-9]+/g,"_").toUpperCase()}`)}function Yr(e){return Object.freeze(e.reasonCodes),Object.freeze(e)}function wt(e,t,r){let n=[],o=e!==null&&typeof e=="object"&&!Array.isArray(e)?e:{},s=t!==null&&typeof t=="object"&&!Array.isArray(t)?t:{},a=r!==null&&typeof r=="object"&&!Array.isArray(r)?r:{},u=ae(o.chainId),l=ae(a.chainId),f=ae(o.lender),d=ae(o.strategy),c=Me(s.supportedChainIds),i=Me(s.allowedLenders),p=Me(s.allowedStrategies);u||B(n,"chainId"),l||B(n,"opts.chainId"),u&&l&&u!==l&&n.push("CHAIN_MISMATCH"),c?(!u||!c.includes(u))&&n.push("UNSUPPORTED_CHAIN"):B(n,"supportedChainIds"),f||B(n,"lender"),i?(!f||!i.includes(f))&&n.push("LENDER_NOT_ALLOWED"):B(n,"allowedLenders"),d||B(n,"strategy"),p?(!d||!p.includes(d))&&n.push("STRATEGY_NOT_ALLOWED"):B(n,"allowedStrategies");let m=Q(o.blockNumber),y=Q(a.currentBlock),S=Q(s.maxBlockDrift);m===null&&B(n,"blockNumber"),y===null&&B(n,"opts.currentBlock"),S===null&&B(n,"maxBlockDrift"),m!==null&&y!==null&&S!==null&&(m>y||y-m>S)&&n.push("STALE_BLOCK"),o.simulationStatus!=="PASS"&&n.push("SIMULATION_NOT_PASS"),o.repaymentStatus!=="PASS"&&n.push("REPAYMENT_NOT_PASS");let A=[["realizedProfitWei","minRealizedProfitWei","PROFIT_BELOW_MINIMUM",(g,h)=>g<h],["gasCostWei","maxGasWei","GAS_LIMIT_EXCEEDED",(g,h)=>g>h],["builderFeeWei","maxBuilderFeeWei","BUILDER_FEE_EXCEEDED",(g,h)=>g>h],["loanPremiumWei","maxLoanPremiumWei","LOAN_PREMIUM_EXCEEDED",(g,h)=>g>h],["loanAmountWei","maxLoanWei","LOAN_LIMIT_EXCEEDED",(g,h)=>g>h]],b={};for(let[g,h,w,N]of A){let x=Q(o[g]),_=Q(s[h]);b[g]=x,x===null&&B(n,g),_===null&&B(n,h),x!==null&&_!==null&&N(x,_)&&n.push(w)}a.armed!==!1&&n.push("NOT_DISARMED");let E={status:n.length===0?"ELIGIBLE":"BLOCKED",reasonCodes:[...new Set(n)],executionReady:!1,mode:"shadow"};return u&&(E.chainId=u),f&&(E.lender=f),d&&(E.strategy=d),m!==null&&(E.blockNumber=m.toString(10)),b.realizedProfitWei!==null&&(E.realizedProfitWei=b.realizedProfitWei.toString(10)),Yr(E)}function W(e){if(e&&typeof e=="object"&&!Object.isFrozen(e)){for(let t of Object.values(e))W(t);Object.freeze(e)}return e}function ce(e){return e instanceof Error&&e.message?e.message.slice(0,300):String(e||"unknown error").slice(0,300)}function Jr(e,t){for(let r of[e?.cycleId,e?.id])if(typeof r=="string"&&r.trim())return r.trim().slice(0,160);return`cycle-${t}`}function Zr(e,t){if(!e||typeof e!="object"||e.profitable===!1)return!1;if(typeof t=="function")return t(e)===!0;if(typeof t?.isProfitable=="function")return t.isProfitable(e)===!0;let r=Number(t?.minNetProfitUsd??0);return Number.isFinite(e.netProfitUsd)&&e.netProfitUsd>=(Number.isFinite(r)?r:0)}function gt({collectCycles:e,evaluateCycle:t,store:r,policy:n={},intervalMs:o=6e4,now:s=Date.now}={}){if(typeof e!="function")throw new Error("collectCycles must be a function");if(typeof t!="function")throw new Error("evaluateCycle must be a function");if(!r||typeof r.append!="function"||typeof r.latest!="function")throw new Error("store must provide append() and latest()");if(!Number.isInteger(o)||o<=0)throw new Error("intervalMs must be a positive integer");if(typeof s!="function")throw new Error("now must be a function");let a=null,u=!1,l=0,f=0,d=null,c=[];function i(){return W({mode:"shadow",execution:!1,signer:!1,broadcaster:!1,running:a!==null,inFlight:u,ticks:l,failures:f,lastError:d})}async function p(){if(u)return W({ok:!1,skipped:"overlap"});u=!0;let E=s(),g=[],h=[],w=[],N=[],x=[];try{try{let I=await e();if(!Array.isArray(I))throw new Error("collectCycles must return an array");x=I}catch(I){g.push({stage:"collect",message:ce(I)})}for(let I=0;I<x.length;I+=1){let R=x[I],T=Jr(R,I);h.push({id:T});try{let C=await t(R,n),j={...C,cycleId:C?.cycleId??T};w.push(j),Zr(C,n)&&N.push({...j,profitable:!0})}catch(C){g.push({stage:"evaluate",cycleId:T,message:ce(C)})}}let _={id:`shadow-${E}-${l+1}`,observedAt:E,cyclesEvaluated:x.length,cycles:h,candidates:w,opportunities:N,errors:g};try{await r.append(_)}catch(I){g.push({stage:"persist",message:ce(I)})}return l+=1,g.length?(f+=1,d=g.map(I=>I.message).join("; ")):d=null,c=r.latest()?.opportunities??W(structuredClone(N)),W({ok:g.length===0,observation:r.latest()??_})}catch(_){return l+=1,f+=1,d=ce(_),W({ok:!1,error:d})}finally{u=!1}}function m(){return a!==null?!1:(a=setInterval(()=>p().catch(()=>{}),o),!0)}function y(){return a===null?!1:(clearInterval(a),a=null,!0)}async function S({timeoutMs:E=3e4}={}){if(!Number.isInteger(E)||E<=0)throw new Error("timeoutMs must be a positive integer");let g=Date.now()+E;for(;u;){if(Date.now()>=g)throw new Error("shadow engine drain timed out");await new Promise(h=>setTimeout(h,5))}return typeof r.drain=="function"&&await r.drain(),!0}function A(){return r.latest()}function b(){return W(structuredClone(c))}return W({tick:p,start:m,stop:y,drain:S,status:i,latest:A,opportunities:b})}import{mkdir as Qr,open as Et,readFile as yt,rename as en,unlink as tn}from"node:fs/promises";import{dirname as rn,basename as nn,join as on}from"node:path";var sn=1e3;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 Fe(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function V(e,t=300){return typeof e=="string"&&e.trim()?e.trim().slice(0,t):void 0}function an(e){if(!e||typeof e!="object")return null;let t={},r=V(e.stage,30),n=V(e.message,300),o=V(e.cycleId,160);return r&&(t.stage=r),n&&(t.message=n),o&&(t.cycleId=o),Object.keys(t).length?t:null}function At(e,{signed:t=!1,max:r=96}={}){return typeof e!="string"||e.length>r?void 0:(t?/^-?(?:0|[1-9][0-9]*)$/:/^(?:0|[1-9][0-9]*)$/).test(e)?e:void 0}function xt(e){if(!e||typeof e!="object"||Array.isArray(e))return null;let t={};for(let r of["cycleId","chain","pair","tokenIn","tokenOut","strategy","venue","lender","qualification","economicStatus","eligibilityStatus","costModel","blockConsistency"]){let n=V(e[r],160);n&&(t[r]=n)}for(let r of["netProfitUsd","grossProfitUsd","costUsd","gasCostUsd","confidence"]){let n=Fe(e[r]);n!==void 0&&(t[r]=n)}for(let r of["amountInWei","amountOutWei","gasUnits","gasCostWei","loanPremiumWei","totalCostWei"]){let n=At(e[r]);n!==void 0&&(t[r]=n)}for(let r of["grossProfitWei","netProfitWei"]){let n=At(e[r],{signed:!0});n!==void 0&&(t[r]=n)}return["PROFITABLE","UNPROFITABLE","STALE","UNAVAILABLE","THEORETICAL"].includes(e.status)&&(t.status=e.status),typeof e.profitable=="boolean"&&(t.profitable=e.profitable),typeof e.economicallyProfitable=="boolean"&&(t.economicallyProfitable=e.economicallyProfitable),e.executionReady===!1&&(t.executionReady=!1),Array.isArray(e.reasonCodes)&&(t.reasonCodes=e.reasonCodes.map(r=>V(r,80)).filter(Boolean).slice(0,32)),Object.keys(t).length?t:null}function cn(e){if(!e||typeof e!="object"||Array.isArray(e))return null;let t={};for(let r of["id","cycleId","chain","tokenIn","tokenOut","strategy"]){let n=V(e[r],160);n&&(t[r]=n)}return Object.keys(t).length?t:null}function St(e,t){let r=e&&typeof e=="object"&&!Array.isArray(e)?e:{},n=Fe(r.observedAt)??Fe(r.timestamp)??t(),o=V(r.id,160)??`shadow-${n}`,s=Array.isArray(r.cycles)?r.cycles.map(cn).filter(Boolean):[],a=Array.isArray(r.opportunities)?r.opportunities.map(xt).filter(Boolean):[],u=Array.isArray(r.candidates)?r.candidates.map(xt).filter(Boolean):[],l=Array.isArray(r.errors)?r.errors.map(an).filter(Boolean):[];return{id:o,observedAt:n,mode:"shadow",cyclesEvaluated:Number.isInteger(r.cyclesEvaluated)&&r.cyclesEvaluated>=0?r.cyclesEvaluated:s.length,cycles:s,candidates:u,opportunities:a,errors:l}}function _t({filePath:e,maxRecords:t=sn,now:r=Date.now,persist:n=!0}={}){if(!Number.isInteger(t)||t<=0)throw new Error("maxRecords must be a positive integer");if(typeof r!="function")throw new Error("now must be a function");if(typeof n!="boolean")throw new Error("persist must be a boolean");if(n&&(typeof e!="string"||!e.trim()))throw new Error("filePath is required when persistence is enabled");let o=[],s=Promise.resolve(),a=()=>G(structuredClone(o));async function u(A){let b=JSON.parse(await yt(A,"utf8")),E=Array.isArray(b)?b:b?.records;if(!Array.isArray(E))throw new Error("shadow store payload is malformed");return E.map(g=>St(g,r)).slice(-t)}async function l(){if(!n)return a();let A=s.then(async()=>{try{o=await u(e)}catch(b){if(b?.code==="ENOENT")try{o=await u(`${e}.bak`)}catch(E){if(E?.code==="ENOENT")o=[];else throw new Error("shadow store backup is corrupted")}else try{o=await u(`${e}.bak`)}catch{throw new Error("shadow store primary and backup are corrupted")}}return a()});return s=A.catch(()=>{}),A}let f=0;async function d(A,b){let E=rn(A),g=on(E,`.${nn(A)}.${process.pid}.${Date.now()}.${f+=1}.tmp`);await Qr(E,{recursive:!0,mode:448});let h;try{h=await Et(g,"wx",384),await h.writeFile(b,"utf8"),await h.sync(),await h.close(),h=null,await en(g,A);let w=await Et(E,"r");try{await w.sync()}finally{await w.close()}}finally{h&&await h.close().catch(()=>{}),await tn(g).catch(()=>{})}}async function c(A){try{let b=await yt(e,"utf8"),E=JSON.parse(b);if(!Array.isArray(E)&&!Array.isArray(E?.records))throw new Error("shadow store payload is malformed");await d(`${e}.bak`,b)}catch(b){if(b?.code!=="ENOENT")throw new Error("refusing to overwrite corrupted shadow store")}await d(e,`${JSON.stringify({version:1,records:A})}
|
|
4
|
+
`)}async function i(A){let b=St(A,r),E=s.then(async()=>{let g=[...o,b].slice(-t);return n&&await c(g),o=g,G(structuredClone(b))});return s=E.catch(()=>{}),E}async function p(){return await s,!0}function m({limit:A}={}){let b=Number.isInteger(A)&&A>=0?o.slice(-A):o;return G(structuredClone(b))}function y(){let A=o.at(-1);return A?G(structuredClone(A)):null}function S(){return G({records:o.length,maxRecords:t,candidates:o.reduce((A,b)=>A+b.candidates.length,0),opportunities:o.reduce((A,b)=>A+b.opportunities.length,0),errors:o.reduce((A,b)=>A+b.errors.length,0)})}return G({append:i,record:i,load:l,drain:p,list:m,latest:y,stats:S})}var vn=/^(?:0|[1-9][0-9]*)$/,de="42161",Xt="arbitrum",Kt="WETH-USDC",pe="arb-weth-usdc-uni-fee-round-trip",me="aave-v3";async function Mn(e){let{collectArbRoundTripCycles:t}=await Promise.resolve().then(()=>(Vt(),Gt));return t(e)}function M(e,t,{positive:r=!1}={}){if(typeof e!="string"||!vn.test(e)||r&&e==="0")throw new TypeError(`${t} must be ${r?"a positive":"a non-negative"} decimal string`);return k(e,t),e}function je(e,t,r,n){if(!Number.isSafeInteger(e)||e<r||e>n)throw new TypeError(`${t} must be an integer from ${r} through ${n}`);return e}function H(e){return e==null?e:structuredClone(e)}function $(e){if(e&&typeof e=="object"&&!Object.isFrozen(e)){for(let t of Object.values(e))$(t);Object.freeze(e)}return e}function Fn(e){return String(e?.message||e||"unknown provider failure").slice(0,300)}function Yt(e={}){let t=M(e.amountInWei,"amountInWei",{positive:!0}),r=M(e.minProfitWei,"minProfitWei"),n=M(e.maxLoanWei,"maxLoanWei"),o=M(e.maxGasWei,"maxGasWei"),s=M(e.builderFeeWei,"builderFeeWei"),a=M(e.extraCostWei,"extraCostWei"),u=M(e.extraGasUnits,"extraGasUnits"),l=je(e.intervalMs,"intervalMs",1,864e5),f=je(e.maxBlockDrift,"maxBlockDrift",0,1e3),d=je(e.maxRecords,"maxRecords",1,1e5),c=e.dependencies??{},i=e.collectCycles??c.collectArbRoundTripCycles??Mn,p=e.readLenderState??c.readArbAaveLenderState??dt,m=e.evaluateEconomics??c.evaluateCycleEconomics??bt,y=e.evaluateEligibility??c.evaluateFlashLoanCandidate??wt,S=e.createEngine??c.createShadowEngine??gt,A=e.createStore??c.createShadowStore??_t;for(let[C,j]of Object.entries({collect:i,readLender:p,evaluateEconomics:m,evaluateEligibility:y,makeEngine:S,makeStore:A}))if(typeof j!="function")throw new TypeError(`${C} dependency must be a function`);let b=A({filePath:e.filePath,persist:e.persist??!0,maxRecords:d,now:e.now??Date.now}),E=[],g=null,h=null,w=null,N=$({async append(C){return await b.append(C),E=[...E,$(H(C))].slice(-d),$(H(C))},async drain(){return typeof b.drain=="function"&&await b.drain(),!0},latest(){return E.length?$(H(E.at(-1))):null}});async function x(){try{w=await p(e.lenderOptions??e)}catch(C){w={status:"UNAVAILABLE",block:null,premiumBps:null,reasons:[Fn(C)]}}if(g=$(H(w)),!w||w.status!=="AVAILABLE")throw new Error(`lender ${w?.status?.toLowerCase()||"unavailable"}: ${(w?.reasons||[]).join("; ")}`);if(!Number.isSafeInteger(w.block)||!Number.isSafeInteger(w.premiumBps)||w.premiumBps<0)throw new Error("lender returned malformed live state");if(h=await i({...e.collectorOptions,amountInWei:t,maxBlockDrift:f,pinnedBlock:w.block}),!h||!Array.isArray(h.cycles))throw new Error("quote provider returned malformed snapshot");if(h.stale===!0||h.blockDrift>f)throw new Error("stale quote snapshot");if(!Number.isSafeInteger(h.blockEnd)||Math.abs(h.blockEnd-w.block)>f)throw new Error("stale lender snapshot relative to quotes");return M(h.gasPriceWei,"quoteSnapshot.gasPriceWei",{positive:!0}),h.cycles}async function _(C){if(!C||C.status!=="OK")throw new Error(C?.error||"cycle quote unavailable");let j=(BigInt(M(C.gasUnits,"cycle.gasUnits"))+BigInt(u)).toString(),ir={...C,gasUnits:j,gasPriceWei:h.gasPriceWei},D=await m(ir,{loanPremiumBps:w.premiumBps,builderFeeWei:s,extraCostWei:a,minProfitWei:r,maxGasWei:o,maxLoanWei:n,maxBlockDrift:f}),Ee=await y({chainId:de,lender:me,strategy:pe,blockNumber:String(h.blockEnd),realizedProfitWei:D.netProfitWei.startsWith("-")?"0":D.netProfitWei,gasCostWei:D.gasCostWei,builderFeeWei:s,loanPremiumWei:D.loanPremiumWei,loanAmountWei:C.amountInWei},{supportedChainIds:[de],allowedLenders:[me],allowedStrategies:[pe],maxBlockDrift:String(f),minRealizedProfitWei:r,maxGasWei:o,maxBuilderFeeWei:s,maxLoanPremiumWei:D.loanPremiumWei,maxLoanWei:n},{chainId:de,currentBlock:String(h.blockEnd),armed:!1}),Ve=[...new Set([...Ee.reasonCodes,"L1_DATA_FEE_NOT_MODELED","EXECUTOR_GAS_NOT_SIMULATED","LENDER_LIQUIDITY_NOT_CHECKED","CROSS_VENUE_CAMELOT_PANCAKE_NOT_QUOTED",...h.blockConsistency==="PINNED"?[]:["QUOTE_BLOCK_NOT_PINNED"]])],ar=D.status==="PROFITABLE"&&Ee.status==="ELIGIBLE"&&Ve.length===0;return $({cycleId:`${C.entryVenue||"unknown"}->${C.exitVenue||"unknown"}`,chain:Xt,pair:Kt,strategy:pe,lender:me,amountInWei:C.amountInWei,amountOutWei:C.amountOutWei,gasUnits:j,...D,status:"THEORETICAL",economicStatus:D.status,economicallyProfitable:D.status==="PROFITABLE",qualification:"THEORETICAL_ONLY",eligibilityStatus:Ee.status,reasonCodes:Ve,costModel:"INCOMPLETE_ESTIMATE",blockConsistency:h.blockConsistency??"RANGE_ONLY",profitable:ar,executionReady:!1,mode:"shadow"})}let I=S({collectCycles:x,evaluateCycle:_,store:N,policy:{isProfitable:C=>C?.profitable===!0},intervalMs:l,now:e.now??Date.now});async function R(){let C=await b.load();return E=H(C).slice(-d),$(H(E))}function T(){return $({mode:"shadow",execution:!1,signer:!1,broadcaster:!1,chain:Xt,chainId:de,pair:Kt,strategy:pe,lender:me,...I.status(),lastProviderState:$(H(g))})}return $({load:R,tick:I.tick,start:I.start,stop:I.stop,drain:I.drain,status:T,latest:N.latest,opportunities:()=>$(H(N.latest()?.opportunities??[]))})}import{createServer as qn}from"node:http";var os=Object.freeze(["chainId","agentAddress","accountAddress","actions","targets","maxValueWei","maxGasWei","maxSlippageBps","expiresAt","nonce","revocationKey"]),ss=Object.freeze(["read","simulate"]);var is=1440*60;var F=class extends Error{constructor(t,r){super(`secret material must never appear in a public API object (at ${t}, rule: ${r})`),this.name="SecretLeakError",this.path=t,this.rule=r}},Un=/(private[_-]?key|secret|bearer|keystore|mnemonic|seed[_-]?phrase|passphrase|password|api[_-]?key|access[_-]?token|auth[_-]?token|session[_-]?token|signer[_-]?url|signature)/i,Wn=Object.freeze(["privkey","wif","xprv","seed"]);function ze(e){let t=String(e),r=t.toLowerCase().replace(/[\s._-]+/g,"");return Un.test(t)||Wn.includes(r)}var Jt=Object.freeze([{rule:"raw-32-byte-hex-key",re:/^0x[0-9a-fA-F]{64}$/},{rule:"raw-32-byte-hex-bare",re:/^[0-9a-fA-F]{64}$/},{rule:"extended-private-key",re:/\b(?:xprv|tprv|yprv|zprv)[1-9A-HJ-NP-Za-km-z]{107}\b/},{rule:"bitcoin-wif",re:/\b[59KLc][1-9A-HJ-NP-Za-km-z]{50,51}\b/},{rule:"bip39-mnemonic",re:/\b(?:[a-z]{3,8}\s+){11,23}[a-z]{3,8}\b/},{rule:"bearer-token",re:/bearer\s+[A-Za-z0-9._~+/=-]+/i},{rule:"pem-private-key",re:/-----BEGIN[A-Z ]*PRIVATE KEY-----/},{rule:"keystore-path",re:/keystore/i},{rule:"signer-url",re:/https?:\/\/\S*sign/i},{rule:"authorization-header",re:/authorization\s*:/i}]),Zt=Object.freeze(["grantid","id","hash","sha256","sha256hex","checksum","txhash","transactionhash","blockhash","digest","userophash","commithash","prevhash","intenthash","canonicalhash","payloadhash","requestid"]);function Hn(e){return e.replace(/"([A-Za-z0-9_-]+)"\s*:\s*"(?:0x)?([0-9a-fA-F]{64})"/g,(t,r)=>Zt.includes(String(r).toLowerCase().replace(/[_-]/g,""))?`"${r}":"<hex64>"`:t)}function Qt(e){let t;try{t=JSON.stringify(e)}catch(o){throw new F("$",`unserializable-payload: ${String(o?.message||o)}`)}if(t===void 0)return"null";let r=Hn(t);for(let{rule:o,re:s}of Jt)if(s.test(r))throw new F("$<serialized>",o);if(/(?:^|[^0-9a-fA-Fx])0x[0-9a-fA-F]{64}(?![0-9a-fA-F])/.test(r))throw new F("$<serialized>","raw-32-byte-hex-embedded");return JSON.parse(t,(o,s)=>{if(o&&ze(o))throw new F(`$<serialized>.${o}`,"forbidden-key-name");return s}),t}function X(e,t="$",r=new Set,n=""){if(e==null)return e;if(typeof e=="string"){let o=Zt.includes(String(n).toLowerCase().replace(/[_-]/g,""));for(let{rule:s,re:a}of Jt)if(!(o&&s.startsWith("raw-32-byte-hex"))&&a.test(e))throw new F(t,s);return e}if(typeof e!="object"||r.has(e)||(r.add(e),ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e;if(e instanceof Map){for(let[o,s]of e.entries()){if(typeof o=="string"&&ze(o))throw new F(`${t}[${JSON.stringify(o)}]`,"forbidden-key-name");X(o,`${t}[key]`,r),X(s,`${t}[${String(o)}]`,r)}return e}if(e instanceof Set){let o=0;for(let s of e.values())X(s,`${t}[${o++}]`,r);return e}if(Array.isArray(e))return e.forEach((o,s)=>X(o,`${t}[${s}]`,r)),e;for(let[o,s]of Object.entries(e)){if(ze(o))throw new F(`${t}.${o}`,"forbidden-key-name");X(s,`${t}.${o}`,r,o)}return e}var er=null,jn="127.0.0.1",zn=8798,Gn=1e6,Vn='{"error":"redacted"}',Xn=Object.freeze({"content-type":"application/json; charset=utf-8","cache-control":"no-store","content-security-policy":"default-src 'none'","x-content-type-options":"nosniff","x-frame-options":"DENY"});function Kn(e){if(!((e==="localhost"||e==="::1"||/^127(?:\.\d{1,3}){3}$/.test(e))&&(!e.startsWith("127.")||e.split(".").slice(1).every(t=>Number(t)<=255))))throw new Error("host must be a loopback address")}function Yn(e){if(!e||["status","latest","opportunities"].some(t=>typeof e[t]!="function"))throw new Error("runtime must provide status(), latest(), and opportunities()")}function Jn(e){typeof er=="function"&&er(e),X(e);let t=Qt(e);if(Buffer.byteLength(t)>Gn)throw new Error("response too large");return t}function q(e,t,r){let n,o=t;try{n=Jn(r)}catch{o=500,n=Vn}e.writeHead(o,{...Xn,"content-length":Buffer.byteLength(n)}),e.end(n)}function tr({runtime:e,host:t=jn,port:r=zn}={}){if(Yn(e),typeof t!="string")throw new Error("host must be a loopback address");if(Kn(t),!Number.isInteger(r)||r<0||r>65535)throw new Error("port must be an integer between 0 and 65535");function n(){let c=e.status(),i=Number.isSafeInteger(c?.ticks)?c.ticks:0,p=typeof c?.lastProviderState?.status=="string"?c.lastProviderState.status:"UNKNOWN",m=c?.running===!0&&i>0&&c?.lastError==null&&p==="AVAILABLE";return{httpStatus:m?200:503,body:{ok:m,ready:m,service:"oracle-mev-shadow",mode:"shadow",execution:!1,signer:!1,broadcaster:!1,ticks:i,provider:p}}}let o=new Map([["/status",()=>e.status()],["/latest",()=>e.latest()],["/opportunities",()=>e.opportunities()]]);async function s(c,i){if(c.method!=="GET"){q(i,405,{error:"method-not-allowed"});return}let p;try{p=new URL(c.url||"/","http://localhost").pathname}catch{q(i,404,{error:"not-found"});return}if(p==="/health"){try{let y=n();q(i,y.httpStatus,y.body)}catch{q(i,503,{error:"redacted"})}return}let m=o.get(p);if(!m){q(i,404,{error:"not-found"});return}try{q(i,200,await m())}catch{q(i,500,{error:"redacted"})}}let a=qn((c,i)=>{s(c,i).catch(()=>{i.headersSent?i.destroy():q(i,500,{error:"redacted"})})}),u=null;function l(){let c=a.address();return c&&typeof c=="object"?{address:c.address,family:c.family,port:c.port}:null}function f(){return a.listening?Promise.resolve(l()):u||(u=new Promise((c,i)=>{let p=y=>{a.off("listening",m),u=null,i(y)},m=()=>{a.off("error",p);let y=l();u=null,c(y)};a.once("error",p),a.once("listening",m),a.listen(r,t)}),u)}async function d(){if(u)try{await u}catch{return!1}return a.listening?(await new Promise((c,i)=>a.close(p=>p?i(p):c())),!0):!1}return Object.freeze({start:f,stop:d,address:l,handler:s})}var rr=/^(?:0|[1-9][0-9]*)$/,to=/^127(?:\.\d{1,3}){3}$/,ro=(1n<<256n)-1n;function be(e){if(e&&typeof e=="object"&&!Object.isFrozen(e)){for(let t of Object.values(e))be(t);Object.freeze(e)}return e}function Ge(e,t){let r=String(e??"").trim().toLowerCase();if(!["","0","false","off"].includes(r))throw new Error(`${t} must remain disarmed for the arb paper shadow service`)}function no(e){return e==="localhost"||e==="::1"?!0:to.test(e)?e.split(".").slice(1).every(t=>Number(t)<=255):!1}function K(e,t,r,{positive:n=!1}={}){let o=String(e[t]??r);if(!rr.test(o)||n&&o==="0")throw new TypeError(`${t} must be ${n?"a positive":"a non-negative"} decimal string`);if(BigInt(o)>ro)throw new RangeError(`${t} must fit uint256`);return o}function he(e,t,r,n,o,s){let a=String(e[t]??r);if(!rr.test(a))throw new TypeError(`${s} must be an integer`);let u=Number(a);if(!Number.isSafeInteger(u)||u<n||u>o)throw new TypeError(`${s} must be an integer from ${n} through ${o}`);return u}function oo(e=process.env){Ge(e.ORACLE_EXECUTE_ENABLED,"ORACLE_EXECUTE_ENABLED"),Ge(e.MAD_EXECUTE_ENABLED,"MAD_EXECUTE_ENABLED"),Ge(e.ORACLE_MEV_EXECUTE_ENABLED,"ORACLE_MEV_EXECUTE_ENABLED");let t=String(e.ORACLE_MEV_ARB_SHADOW_HOST??"127.0.0.1").trim();if(!no(t))throw new Error("ORACLE_MEV_ARB_SHADOW_HOST must be loopback-only");let r=String(e.HOME||Zn()),n=String(e.ORACLE_MEV_ARB_SHADOW_STATE??eo(r,".local/state/oracle/mev-arb-shadow/observations.json"));if(!Qn(n))throw new Error("ORACLE_MEV_ARB_SHADOW_STATE must be an absolute path");let o=String(e.ORACLE_MEV_ARB_SHADOW_PERSIST??"1").trim();if(!["0","1"].includes(o))throw new Error("persist must be 0 or 1");return be({host:t,port:he(e,"ORACLE_MEV_ARB_SHADOW_PORT","8809",0,65535,"port"),intervalMs:he(e,"ORACLE_MEV_ARB_SHADOW_INTERVAL_MS","15000",1e3,864e5,"intervalMs"),amountInWei:K(e,"ORACLE_MEV_ARB_SHADOW_AMOUNT_IN_WEI","1000000000000000000",{positive:!0}),minProfitWei:K(e,"ORACLE_MEV_ARB_SHADOW_MIN_PROFIT_WEI","10000000000000"),maxLoanWei:K(e,"ORACLE_MEV_ARB_SHADOW_MAX_LOAN_WEI","5000000000000000000",{positive:!0}),maxGasWei:K(e,"ORACLE_MEV_ARB_SHADOW_MAX_GAS_WEI","500000000000000"),builderFeeWei:K(e,"ORACLE_MEV_ARB_SHADOW_BUILDER_FEE_WEI","0"),extraCostWei:K(e,"ORACLE_MEV_ARB_SHADOW_EXTRA_COST_WEI","0"),extraGasUnits:K(e,"ORACLE_MEV_ARB_SHADOW_EXTRA_GAS_UNITS","250000"),maxBlockDrift:he(e,"ORACLE_MEV_ARB_SHADOW_MAX_BLOCK_DRIFT","40",0,1e3,"maxBlockDrift"),maxRecords:he(e,"ORACLE_MEV_ARB_SHADOW_MAX_RECORDS","500",1,1e5,"maxRecords"),filePath:n,persist:o==="1"})}function nr({env:e=process.env,runtimeFactory:t=Yt,serverFactory:r=tr}={}){if(typeof t!="function"||typeof r!="function")throw new TypeError("runtimeFactory and serverFactory must be functions");let n=oo(e),o=t(n),s=r({runtime:o,host:n.host,port:n.port}),a=null,u=null;async function l(){return a||u||(u=(async()=>{let c=!1;try{await o.load();let i=await o.tick();o.start(),c=!0;let p=await s.start();return a=be({mode:"shadow",chain:"arbitrum",chainId:42161,execution:!1,signer:!1,broadcaster:!1,address:p,initialTick:i}),a}catch(i){try{await s.stop()}catch{}if(c)try{o.stop(),typeof o.drain=="function"&&await o.drain()}catch{}throw i}finally{u=null}})(),u)}async function f(){if(u)try{await u}catch{}if(!a)return!1;let c=null;try{await s.stop()}catch(i){c=i}if(o.stop(),typeof o.drain=="function"&&await o.drain(),a=null,c)throw c;return!0}function d(){return be({mode:"shadow",chain:"arbitrum",chainId:42161,execution:!1,signer:!1,broadcaster:!1,listening:!!a,address:s.address(),runtime:o.status()})}return Object.freeze({start:l,stop:f,status:d,config:n})}var we="oracle-mev-arb-shadow";function ge(e,t){e.write(`${JSON.stringify(t)}
|
|
5
|
+
`)}async function or({env:e=process.env,appFactory:t=nr,stdout:r=process.stdout,stderr:n=process.stderr,processLike:o=process}={}){if(typeof t!="function")throw new TypeError("appFactory must be a function");if(!r||typeof r.write!="function"||!n||typeof n.write!="function")throw new TypeError("stdout and stderr must be writable streams");if(!o||typeof o.once!="function")throw new TypeError("processLike must provide once()");let s=t({env:e}),a=null;async function u(d="shutdown"){return a||(a=(async()=>{try{return await s.stop(),ge(r,{event:"stopped",service:we,signal:d}),!0}catch{return o.exitCode=1,ge(n,{event:"fatal",service:we,error:"shutdown failed"}),!1}})(),a)}for(let d of["SIGINT","SIGTERM"])o.once(d,()=>{u(d).catch(()=>{o.exitCode=1})});let l;try{l=await s.start()}catch{throw o.exitCode=1,ge(n,{event:"fatal",service:we,error:"startup failed"}),new Error("arb paper shadow service failed to start")}let f=l?.address&&typeof l.address=="object"?l.address:{};return ge(r,{event:"listening",service:we,mode:"shadow",chain:"arbitrum",chainId:42161,execution:!1,signer:!1,broadcaster:!1,address:f.address??null,family:f.family??null,port:f.port??null}),Object.freeze({app:s,stop:u})}var sr=process.argv.slice(2);(sr.includes("--help")||sr.includes("-h"))&&(process.stdout.write(`Usage: oracle-mev-arb-shadow [--help]
|
|
6
|
+
Loopback-only Arbitrum paper MEV observer. Never prepares, signs, or broadcasts.
|
|
7
|
+
`),process.exit(0));or().catch(()=>{process.exitCode=1});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{homedir as K}from"node:os";import{join as y}from"node:path";import{createHmac as pe,randomUUID as ve,timingSafeEqual as re}from"node:crypto";import{mkdir as C,open as L,readFile as A,rename as me,lstat as D,unlink as ye}from"node:fs/promises";import{basename as Ee,dirname as T,join as ge}from"node:path";import{createHmac as ce,timingSafeEqual as se,randomUUID as ue}from"node:crypto";import{lstat as fe,mkdir as le,open as W,readFile as Y,rename as de}from"node:fs/promises";import{dirname as we}from"node:path";function F(e){return Array.isArray(e)?`[${e.map(F).join(",")}]`:e&&typeof e=="object"?`{${Object.keys(e).sort().map(o=>`${JSON.stringify(o)}:${F(e[o])}`).join(",")}}`:JSON.stringify(e)}function X(e){let o=Buffer.isBuffer(e)?e:Buffer.from(String(e||""));if(o.length<32||o.length>128)throw new Error("monotonic anchor key length is invalid");return o}function G(e){return/^(?:0x)?[0-9a-f]{64}$/i.test(String(e))}function J(e){let o=String(e).toLowerCase();return o.startsWith("0x")?o:`0x${o}`}function Q(e,o){return`0x${ce("sha256",X(e)).update("oracle-monotonic-anchor-v1\0").update(F(o)).digest("hex")}`}async function Z(e,o,r){let t=await fe(e);if(t.isSymbolicLink()||!t.isFile()||(t.mode&63)!==0||t.size>r||typeof process.getuid=="function"&&t.uid!==process.getuid())throw new Error(`${o} permissions, type, owner, or size are unsafe`);return t}async function he(e,o){let r=we(e);await le(r,{recursive:!0,mode:448});let t=`${e}.${process.pid}.${ue()}.tmp`,n=await W(t,"wx",384);try{await n.writeFile(o),await n.sync()}finally{await n.close()}await de(t,e);let i=await W(r,"r");try{await i.sync()}finally{await i.close()}}async function R(e){return await Z(e,"monotonic anchor key",128),X(await Y(e))}async function P({path:e,key:o,domain:r}={}){if(typeof e!="string"||!e||typeof r!="string"||!/^[a-z0-9:_-]{1,80}$/i.test(r))throw new TypeError("monotonic anchor path and domain are required");await Z(e,"monotonic anchor",4096);let t=JSON.parse(await Y(e,"utf8")),n=t?.base;if(!n||n.version!==1||n.domain!==r||!Number.isSafeInteger(n.revision)||n.revision<1||!G(n.digest)||!Number.isSafeInteger(n.updatedAt)||!/^0x[0-9a-f]{64}$/i.test(String(t.mac||"")))throw new Error("monotonic anchor is invalid");let i=Buffer.from(Q(o,n).slice(2),"hex"),v=Buffer.from(t.mac.slice(2),"hex");if(v.length!==i.length||!se(v,i))throw new Error("monotonic anchor authentication failed");return Object.freeze({...n,digest:J(n.digest)})}async function ee({path:e,key:o,domain:r,revision:t,digest:n}={}){let i=await P({path:e,key:o,domain:r});if(i.revision!==t||i.digest!==J(n))throw new Error("monotonic anchor rollback or divergence detected");return i}async function V({path:e,key:o,domain:r,revision:t,digest:n,now:i=Date.now,allowInitializeAtRevision:v=!1}={}){if(!Number.isSafeInteger(t)||t<1||!G(n)||typeof i!="function")throw new TypeError("monotonic anchor revision, digest, and clock are required");let w=null;try{w=await P({path:e,key:o,domain:r})}catch(O){if(O?.code!=="ENOENT")throw O}if(w){if(t!==w.revision+1)throw new Error("monotonic anchor revision must advance exactly once")}else if(t!==1&&v!==!0)throw new Error("monotonic anchor initialization revision is unsafe");let E={version:1,domain:r,revision:t,digest:J(n),updatedAt:i()},b={base:E,mac:Q(o,E)};return await he(e,`${JSON.stringify(b)}
|
|
3
|
+
`),Object.freeze(E)}function m(e,o,r){if(typeof e!="string"||!e.trim()||e.length>r||/[\u0000-\u001f\u007f]/.test(e))throw new TypeError(`${o} must be non-empty printable text up to ${r} characters`);return e.trim()}function be(e){let o=String(e??"");if(!/^[1-9][0-9]{0,19}$/.test(o))throw new TypeError("chainId must be a positive decimal string");return o}function $(e,o){return pe("sha256",e).update(o).digest("hex")}function k(e){let o={};for(let t of Object.keys(e.chains??{}).sort()){let n=e.chains[t];o[t]={revoked:n.revoked,armed:n.armed,revision:n.revision}}let r={version:1,revision:e.revision,globalRevoked:e.globalRevoked,chains:o,updatedAt:e.updatedAt,actor:e.actor,reason:e.reason};return e.authorizationId!=null&&(r.authorizationId=String(e.authorizationId).toLowerCase()),e.authorizationExpiresAt!=null&&(r.authorizationExpiresAt=e.authorizationExpiresAt),r}function Oe(e){return!e||typeof e!="object"||Array.isArray(e)||e.version!==1||!Number.isSafeInteger(e.revision)||e.revision<1||typeof e.globalRevoked!="boolean"||!e.chains||typeof e.chains!="object"||Array.isArray(e.chains)||!Number.isSafeInteger(e.updatedAt)||e.authorizationId!=null&&!/^0x[0-9a-fA-F]{64}$/.test(String(e.authorizationId))||e.authorizationId==null&&e.authorizationExpiresAt!=null||e.authorizationId!=null&&(!Number.isSafeInteger(e.authorizationExpiresAt)||e.authorizationExpiresAt<=e.updatedAt)||typeof e.actor!="string"||typeof e.reason!="string"?!1:Object.entries(e.chains).every(([o,r])=>{let t=r?.revoked===!0&&r?.armed===!1,n=r?.revoked===!1&&r?.armed===!0;return/^[1-9][0-9]{0,19}$/.test(o)&&r&&typeof r=="object"&&(t||!e.globalRevoked&&n)&&Number.isSafeInteger(r.revision)&&r.revision>=1&&r.revision<=e.revision})}async function B(e,o,r){let t=await D(e);if(t.isSymbolicLink()||!t.isFile()||(t.mode&63)!==0||t.size>r||typeof process.getuid=="function"&&t.uid!==process.getuid())throw new Error(`${o} permissions, type, or size are unsafe`);return t}async function x(e){await B(e,"control key",128);let o=await A(e);if(o.length<32||o.length>128)throw new Error("control key length is invalid");return o}async function ke(e){let o=await L(e,"r");try{await o.sync()}finally{await o.close()}}async function Ae(e,o){let r=T(e);await C(r,{recursive:!0,mode:448});let t=ge(r,`.${Ee(e)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`),n=await L(t,"wx",384);try{await n.writeFile(o),await n.sync()}finally{await n.close()}await me(t,e),await ke(r)}function I(e,o){let r=k(e),t=JSON.stringify(r);return{state:r,mac:$(o,t)}}async function z(e,o){await B(e,"revocation state",1048576);let r=JSON.parse(await A(e,"utf8"));if(!r||typeof r!="object"||typeof r.mac!="string"||!Oe(r.state))throw new Error("revocation state invalid");let t=Buffer.from($(o,JSON.stringify(k(r.state))),"hex"),n=Buffer.from(r.mac,"hex");if(n.length!==t.length||!re(n,t))throw new Error("revocation state authentication failed");return k(r.state)}async function Se(e){await C(T(e),{recursive:!0,mode:448});for(let o=0;o<100;o+=1)try{let r=await L(e,"wx",384),t=ve();return await r.writeFile(`${JSON.stringify({version:1,pid:process.pid,token:t})}
|
|
4
|
+
`),await r.sync(),{handle:r,token:t}}catch(r){if(r?.code!=="EEXIST")throw r;let t;try{t=await D(e)}catch(i){if(i?.code==="ENOENT")continue;throw i}if(t.isSymbolicLink()||!t.isFile()||(t.mode&63)!==0||t.size>256||typeof process.getuid=="function"&&t.uid!==process.getuid())throw new Error("revocation control lock permissions, type, or size are unsafe");let n;try{n=JSON.parse(await A(e,"utf8"))}catch(i){if(i?.code==="ENOENT")continue;throw new Error("revocation control lock metadata invalid")}if(n?.version!==1||!Number.isSafeInteger(n.pid)||n.pid<1||typeof n.token!="string"||!/^[0-9a-f-]{36}$/i.test(n.token))throw new Error("revocation control lock metadata invalid");try{process.kill(n.pid,0)}catch(i){if(i?.code==="ESRCH")throw new Error("stale revocation control lock requires manual recovery");if(i?.code!=="EPERM")throw i}await new Promise(i=>setTimeout(i,10))}throw new Error("revocation control lock unavailable")}async function Ne(e,o){try{let[r,t]=await Promise.all([o.handle.stat(),D(e)]),n=JSON.parse(await A(e,"utf8"));if(!t.isFile()||t.isSymbolicLink()||r.dev!==t.dev||r.ino!==t.ino||n?.version!==1||n.pid!==process.pid||n.token!==o.token)throw new Error("revocation control lock ownership changed; refusing unsafe release");await ye(e)}finally{await o.handle.close().catch(()=>{})}}function oe({keyPath:e,statePath:o,auditPath:r,anchorPath:t,anchorKeyPath:n,fencePath:i,actor:v,now:w=Date.now}={}){m(e,"keyPath",1e3),m(o,"statePath",1e3),m(r,"auditPath",1e3),m(t,"anchorPath",1e3),m(n,"anchorKeyPath",1e3),m(i,"fencePath",1e3);let E=m(v,"actor",80);if(typeof w!="function")throw new TypeError("now must be a function");let b=i,O=Promise.resolve();async function M(c){let a;try{await B(r,"revocation audit",16*1024*1024),a=await A(r,"utf8")}catch(l){if(l?.code==="ENOENT")return[];throw l}let s=a.split(`
|
|
5
|
+
`).filter(Boolean),u=[],d=null,f=0;for(let l=0;l<s.length;l+=1){let h=JSON.parse(s[l]);if(!h||typeof h!="object"||Array.isArray(h)||typeof h.recordMac!="string")throw new Error("revocation audit record invalid");let{recordMac:g,...p}=h,N=Buffer.from($(c,JSON.stringify(p)),"hex"),_=Buffer.from(g,"hex");if(_.length!==N.length||!re(_,N)||p.version!==1||p.auditSeq!==l+1||p.prevRecordMac!==d||!Number.isSafeInteger(p.revision)||(l===0?p.revision<1:p.revision!==f+1)||typeof p.stateMac!="string")throw new Error("revocation audit authentication failed");u.push(h),d=g,f=p.revision}return u}async function j(c,a){let s=await M(a),u=s.at(-1),d=I(c,a).mac;if(!u||u.revision!==c.revision||u.stateMac!==d)throw new Error("revocation state and audit revision mismatch");let f=await R(n);return await ee({path:t,key:f,domain:"oracle-revocation",revision:c.revision,digest:d}),s}async function te(){try{let c=await x(e),a=await z(o,c);return await j(a,c),Object.freeze({authenticated:!0,state:Object.freeze(structuredClone(a))})}catch{return Object.freeze({authenticated:!1,state:null})}}async function ne(c,a,s){let u=await M(s),d={version:1,auditSeq:u.length+1,prevRecordMac:u.at(-1)?.recordMac??null,action:c,revision:a.revision,updatedAt:a.updatedAt,actor:a.actor,reason:a.reason,stateMac:I(a,s).mac},f={...d,recordMac:$(s,JSON.stringify(d))};await C(T(r),{recursive:!0,mode:448});let l=await L(r,"a",384);try{await l.writeFile(`${JSON.stringify(f)}
|
|
6
|
+
`),await l.sync()}finally{await l.close()}}async function H(c,a,s){let u=I(a,s);await Ae(o,`${JSON.stringify(u)}
|
|
7
|
+
`),await ne(c,a,s);let d=await R(n);return await V({path:t,key:d,domain:"oracle-revocation",revision:a.revision,digest:u.mac,now:w,allowInitializeAtRevision:c==="BOOTSTRAP_REVOKED"}),Object.freeze(structuredClone(a))}function S(c){let a=O.then(async()=>{await C(T(b),{recursive:!0,mode:448});let s=await Se(b);try{return await c()}finally{await Ne(b,s)}});return O=a.catch(()=>{}),a}function ie({reason:c,initialRevision:a=1}={}){let s=m(c,"reason",240);if(!Number.isSafeInteger(a)||a<1)throw new TypeError("initialRevision must be a positive safe integer");return S(async()=>{let u=await x(e);try{let f=await z(o,u);return await j(f,u),Object.freeze(f)}catch(f){if(f?.code!=="ENOENT")throw f}let d=k({revision:a,globalRevoked:!0,chains:{},updatedAt:w(),actor:E,reason:s});return H("BOOTSTRAP_REVOKED",d,u)})}function U(c,{reason:a,expectedRevision:s,chainId:u}={}){let d=m(a,"reason",240);if(s!==void 0&&(!Number.isSafeInteger(s)||s<1))throw new TypeError("expectedRevision must be a positive integer");let f=u===void 0?null:be(u);return S(async()=>{let l=await x(e),h=await z(o,l);if(await j(h,l),s!==void 0&&h.revision!==s)throw new Error(`revision conflict: expected ${s}, found ${h.revision}`);let g=h.revision+1,p=structuredClone(h.chains);if(f)p[f]={revoked:!0,armed:!1,revision:g};else for(let _ of Object.keys(p))p[_]={revoked:!0,armed:!1,revision:g};let N=k({...h,revision:g,globalRevoked:f?h.globalRevoked:!0,authorizationId:null,authorizationExpiresAt:null,chains:p,updatedAt:w(),actor:E,reason:d});return H(c,N,l)})}function ae({expectedRevision:c}={}){if(!Number.isSafeInteger(c)||c<1)throw new TypeError("expectedRevision must be a positive integer");return S(async()=>{let a=await x(e),s=await z(o,a),u=await M(a),d=I(s,a).mac,f=u.at(-1);if(!f||f.revision!==s.revision||f.stateMac!==d)throw new Error("revocation state and audit revision mismatch");if(s.globalRevoked!==!0||s.revision!==c)throw new Error("only an exact currently revoked revision may initialize the anchor");let l=await R(n);return await V({path:t,key:l,domain:"oracle-revocation",revision:s.revision,digest:d,now:w,allowInitializeAtRevision:!0}),Object.freeze(structuredClone(s))})}return Object.freeze({bootstrapRevoked:ie,readSnapshot:te,anchorCurrentRevoked:ae,revokeAll:c=>U("REVOKE_ALL",c),revokeChain:c=>U("REVOKE_CHAIN",c),withFence:c=>{if(typeof c!="function")throw new TypeError("fenced operation must be a function");return S(c)}})}function _e(e){let o={};for(let r=0;r<e.length;r+=1){let t=e[r];if(!t.startsWith("--"))throw new Error(`unexpected argument: ${t}`);let n=e[r+1];if(n===void 0||n.startsWith("--"))throw new Error(`${t} requires a value`);o[t.slice(2)]=n,r+=1}return o}function q(e){if(e===void 0)return;if(!/^[1-9][0-9]*$/.test(e))throw new Error("expected-revision must be a positive integer");let o=Number(e);if(!Number.isSafeInteger(o))throw new Error("expected-revision must be a safe integer");return o}function Re(e){return{authenticated:!0,version:e.version,revision:e.revision,globalRevoked:e.globalRevoked,authorizationId:e.authorizationId??null,authorizationExpiresAt:e.authorizationExpiresAt??null,chains:e.chains,updatedAt:e.updatedAt,actor:e.actor,reason:e.reason}}async function xe(){let[e,...o]=process.argv.slice(2);if(!e)throw new Error("command required: status, bootstrap-revoked, anchor-current-revoked, revoke-chain, revoke-all");let r=_e(o),t=y(K(),".local/state/oracle/mev-control"),n=process.env.ORACLE_MEV_CONTROL_ANCHOR_DIR??y(K(),".local/state/oracle/mev-control-anchor"),i=oe({keyPath:process.env.ORACLE_MEV_CONTROL_KEY_FILE??process.env.ORACLE_MEV_CONTROL_KEY??y(t,"control.key"),statePath:process.env.ORACLE_MEV_CONTROL_STATE_FILE??process.env.ORACLE_MEV_CONTROL_STATE??y(t,"state.json"),auditPath:process.env.ORACLE_MEV_CONTROL_AUDIT_FILE??process.env.ORACLE_MEV_CONTROL_AUDIT??y(t,"audit.jsonl"),anchorPath:process.env.ORACLE_MEV_REVOCATION_ANCHOR_FILE??y(n,"revocation.json"),anchorKeyPath:process.env.ORACLE_MEV_ANCHOR_KEY_FILE??y(n,"anchor.key"),fencePath:process.env.ORACLE_MEV_FENCE_FILE??y(K(),".local/state/oracle/mev-fence/control.lock"),actor:process.env.ORACLE_MEV_CONTROL_ACTOR??"oracle-owner"}),v;if(e==="status"){if(Object.keys(r).length)throw new Error("status accepts no options");let w=await i.readSnapshot();if(!w.authenticated)throw new Error("revocation state unavailable or unauthenticated");v=w.state}else if(e==="bootstrap-revoked")v=await i.bootstrapRevoked({reason:r.reason});else if(e==="anchor-current-revoked"){if(Object.keys(r).some(w=>w!=="expected-revision"))throw new Error("anchor-current-revoked accepts only --expected-revision");v=await i.anchorCurrentRevoked({expectedRevision:q(r["expected-revision"])})}else if(e==="revoke-chain")v=await i.revokeChain({chainId:r["chain-id"],reason:r.reason,expectedRevision:q(r["expected-revision"])});else if(e==="revoke-all")v=await i.revokeAll({reason:r.reason,expectedRevision:q(r["expected-revision"])});else throw new Error(`unknown command: ${e}`);process.stdout.write(`${JSON.stringify(Re(v))}
|
|
8
|
+
`)}xe().catch(e=>{process.stderr.write(`${String(e?.message||"control command failed").slice(0,500)}
|
|
9
|
+
`),process.exitCode=1});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{randomBytes as u}from"node:crypto";import{mkdir as y,open as f,rm as m}from"node:fs/promises";import{resolve as n}from"node:path";import{Wallet as p}from"ethers";function g(e){let t,r=!1;for(let s=0;s<e.length;s+=1){let o=e[s];if(o==="--directory")t=e[++s];else if(o==="--json")r=!0;else throw new Error(`unknown argument: ${o}`)}if(!t)throw new Error("--directory is required");return{directory:n(t),json:r}}async function c(e,t){let r=await f(e,"wx",384);try{await r.writeFile(t),await r.sync()}finally{await r.close()}}async function h(){let{directory:e,json:t}=g(process.argv.slice(2));await y(e,{recursive:!0,mode:448});let r=n(e,"signer.keystore.json"),s=n(e,"signer.password"),o=p.createRandom(),a=u(48).toString("base64url"),d=await o.encrypt(a),i=!1;try{await c(s,a),i=!0,await c(r,d)}catch(w){throw i&&await m(s,{force:!0}),w}let l={created:!0,address:o.address};process.stdout.write(t?`${JSON.stringify(l)}
|
|
3
|
+
`:`Created dedicated MEV signer ${o.address}
|
|
4
|
+
`)}h().catch(e=>{process.stderr.write(`oracle-mev-keygen: ${e.message}
|
|
5
|
+
`),process.exitCode=1});
|