@oracle-agent/oracle 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/bin/oracle-data-mcp.mjs +32 -0
  2. package/package.json +1 -1
  3. package/public/oracle-splash/assets/llms/claude.svg +1 -1
  4. package/public/oracle-splash/assets/llms/codex.svg +1 -1
  5. package/public/oracle-splash/assets/llms/cursor-icon.svg +12 -0
  6. package/public/oracle-splash/assets/llms/cursor.svg +1 -1
  7. package/public/oracle-splash/assets/llms/deepseek.svg +1 -1
  8. package/public/oracle-splash/assets/llms/gemini.svg +1 -1
  9. package/public/oracle-splash/assets/llms/kimi-icon.svg +1 -0
  10. package/public/oracle-splash/assets/llms/kimi.svg +1 -1
  11. package/public/oracle-splash/assets/llms/openclaw.svg +1 -1
  12. package/public/oracle-splash/assets/llms/perplexity.svg +1 -1
  13. package/public/oracle-splash/assets/llms/qwen.svg +1 -1
  14. package/public/oracle-splash/assets/wordmarks/cowswap.svg +1 -1
  15. package/public/oracle-splash/assets/wordmarks/curve.png +0 -0
  16. package/public/oracle-splash/assets/wordmarks/gmx.svg +1 -1
  17. package/public/oracle-splash/assets/wordmarks/kinetiq.svg +1 -0
  18. package/public/oracle-splash/assets/wordmarks/lfj.webp +0 -0
  19. package/public/oracle-splash/assets/wordmarks/magic-eden.svg +1 -1
  20. package/public/oracle-splash/assets/wordmarks/morpho.svg +1 -1
  21. package/public/oracle-splash/assets/wordmarks/odos.svg +1 -1
  22. package/public/oracle-splash/assets/wordmarks/opensea.svg +1 -1
  23. package/public/oracle-splash/assets/wordmarks/paragon.svg +9 -0
  24. package/public/oracle-splash/assets/wordmarks/paraswap.svg +1 -1
  25. package/public/oracle-splash/index.html +85 -95
  26. package/src/data/catalog.mjs +11 -0
  27. package/src/data/desk-data.mjs +6 -0
  28. package/src/data/providers/rfq.mjs +15 -0
  29. package/src/index.mjs +7 -0
  30. package/src/rfq/intent.mjs +180 -0
  31. package/src/rfq/sources.mjs +181 -0
  32. package/protocols/templates/safe-erc20/README.md +0 -9
@@ -18,9 +18,9 @@
18
18
  --blue:#7CC4FF;
19
19
  --blue2:#A7D8FF;
20
20
  --blue-dim:#3a6f99;
21
- --ink:#E8F1FA;
22
- --cool:#B7CCE0;
23
- --mute:#89A3BE;
21
+ --ink:#F4F9FE;
22
+ --cool:#C9DAEC;
23
+ --mute:#9FB8D2;
24
24
  --line:rgba(124,196,255,.14);
25
25
  --line-2:rgba(124,196,255,.24);
26
26
  --evm:#7CC4FF;
@@ -40,7 +40,7 @@
40
40
  html{scroll-behavior:smooth;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
41
41
  body{
42
42
  min-height:100dvh;background:var(--bg);color:var(--ink);position:relative;isolation:isolate;
43
- font-family:var(--sans);font-weight:350;overflow-x:hidden;
43
+ font-family:var(--sans);font-weight:400;overflow-x:hidden;
44
44
  }
45
45
  ::selection{background:var(--blue);color:#061018}
46
46
  a{color:inherit;text-decoration:none}
@@ -117,7 +117,7 @@ img{display:inline-block}
117
117
  .nav-cta:hover{border-color:var(--blue);color:var(--blue2);box-shadow:0 0 0 1px rgba(124,196,255,.12)}
118
118
 
119
119
  /* fixed soft field behind content */
120
- #gl{position:fixed;inset:0;width:100%;height:100%;z-index:-1;display:block;opacity:.75;pointer-events:none}
120
+ #gl{position:fixed;inset:0;width:100%;height:100%;z-index:-1;display:block;opacity:.4;pointer-events:none}
121
121
  .veil{
122
122
  position:fixed;inset:0;z-index:1;pointer-events:none;
123
123
  background:
@@ -147,7 +147,7 @@ main{position:relative;z-index:2;padding-top:84px}
147
147
  .hero-stage{position:relative;width:100%;display:grid;place-items:center;min-height:clamp(360px,52vh,560px)}
148
148
  .hero-art{position:absolute;inset:0;display:grid;place-items:center;z-index:0;pointer-events:none}
149
149
  #orb-vid{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:min(74vw,620px);aspect-ratio:1;object-fit:contain;opacity:0;transition:opacity 1.4s var(--ease);mix-blend-mode:screen}
150
- #orb-vid.ready{opacity:.5}
150
+ #orb-vid.ready{opacity:.62}
151
151
  .blender-orb .hero-orb{display:none}
152
152
  .hero-orb{
153
153
  width:clamp(380px,50vw,640px);aspect-ratio:1;position:relative;transform-style:preserve-3d;
@@ -195,12 +195,12 @@ main{position:relative;z-index:2;padding-top:84px}
195
195
  .hero-note{font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--mute)}
196
196
  @keyframes orb-slew{0%{transform:rotateX(18deg) rotateZ(-8deg) rotateY(0deg)}100%{transform:rotateX(18deg) rotateZ(-8deg) rotateY(360deg)}}
197
197
  @keyframes home-breathe{0%,100%{opacity:.65;transform:scale(1)}50%{opacity:1;transform:scale(1.07)}}
198
- @keyframes drop-line{0%,100%{opacity:.25;transform:translateX(-50%) scaleY(.45)}50%{opacity:1;transform:translateX(-50%) scaleY(1)}}}
198
+ @keyframes drop-line{0%,100%{opacity:.25;transform:translateX(-50%) scaleY(.45)}50%{opacity:1;transform:translateX(-50%) scaleY(1)}}
199
199
 
200
200
 
201
201
  .section{
202
202
  position:relative;z-index:2;max-width:var(--max);margin:0 auto;
203
- padding:clamp(28px,5vh,48px) var(--pad) 0;
203
+ padding:clamp(56px,10vh,110px) var(--pad) 0;
204
204
  }
205
205
  .section:first-of-type{padding-top:clamp(18px,3vh,28px)}
206
206
  .section-label{
@@ -213,7 +213,7 @@ main{position:relative;z-index:2;padding-top:84px}
213
213
  max-width:18ch;margin-bottom:12px;
214
214
  }
215
215
  .section-title em{font-style:italic;color:var(--blue2)}
216
- .section-lede{max-width:52ch;color:#B7CCE0;font-size:16px;line-height:1.7;margin-bottom:clamp(28px,4vw,44px)}
216
+ .section-lede{max-width:52ch;color:#C9DAEC;font-size:16px;line-height:1.7;margin-bottom:clamp(28px,4vw,44px)}
217
217
 
218
218
  /* orchestration graph */
219
219
  .graph-shell{
@@ -223,7 +223,7 @@ main{position:relative;z-index:2;padding-top:84px}
223
223
  .graph-top{
224
224
  display:flex;flex-wrap:wrap;justify-content:center;gap:10px;
225
225
  padding:14px 18px;border-bottom:1px solid var(--line);
226
- font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:#88A6C2;
226
+ font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:#9FB8D2;
227
227
  }
228
228
  .graph-top b{color:var(--blue);font-weight:500}
229
229
  .graph-canvas{padding:clamp(28px,4vw,40px) clamp(14px,2.5vw,24px) clamp(22px,3vw,30px);overflow:auto}
@@ -262,11 +262,11 @@ main{position:relative;z-index:2;padding-top:84px}
262
262
  display:flex;flex-direction:column;align-items:center;
263
263
  }
264
264
  .node.hub .orbital{width:74px;height:74px;margin:2px 0 10px;filter:drop-shadow(0 0 20px rgba(124,196,255,.35))}
265
- .node .tag{font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:#88A6C2;margin-bottom:8px}
265
+ .node .tag{font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:#9FB8D2;margin-bottom:8px}
266
266
  .node.hub .tag{color:var(--blue)}
267
267
  .node .name{font-family:var(--display);font-size:22px;font-weight:500;color:#DCEAF6;line-height:1;letter-spacing:.01em;margin-bottom:6px}
268
268
  .node.hub .name{font-size:34px;font-weight:400;font-style:italic}
269
- .node .sub{font-family:var(--mono);font-size:11px;letter-spacing:.05em;color:#AAC4DC;line-height:1.5}
269
+ .node .sub{font-family:var(--mono);font-size:11px;letter-spacing:.05em;color:#C9DAEC;line-height:1.5}
270
270
  .node.route{min-height:138px;display:flex;flex-direction:column;justify-content:flex-start;text-align:left;padding:14px}
271
271
  .node.route .name{font-size:18px;margin-bottom:8px}
272
272
  .node.route .chains{
@@ -362,14 +362,14 @@ main{position:relative;z-index:2;padding-top:84px}
362
362
  margin-top:22px;
363
363
  }
364
364
  .moat-card{
365
- background:var(--bg);padding:clamp(20px,3vw,28px);min-height:140px;
365
+ background:rgba(17,25,37,.94);padding:clamp(20px,3vw,28px);min-height:140px;
366
366
  display:flex;flex-direction:column;gap:10px;
367
367
  transition:background .35s;
368
368
  }
369
369
  .moat-card:hover{background:var(--panel-2)}
370
370
  .moat-card .n{font-family:var(--mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--blue)}
371
371
  .moat-card h3{font-family:var(--display);font-weight:400;font-size:clamp(20px,2.2vw,26px)}
372
- .moat-card p{color:#B7CCE0;font-size:15px;line-height:1.55;max-width:44ch}
372
+ .moat-card p{color:#C9DAEC;font-size:15px;line-height:1.55;max-width:44ch}
373
373
  @media (max-width:860px){.moat-grid{grid-template-columns:1fr}}
374
374
  .evolve-rail{
375
375
  display:flex;flex-wrap:wrap;gap:8px;justify-content:center;
@@ -405,7 +405,7 @@ main{position:relative;z-index:2;padding-top:84px}
405
405
  .wires.multi circle.c-sol{fill:var(--sol)}
406
406
 
407
407
  /* route detail cards */
408
- .route-card{
408
+ .route-card{background:rgba(17,25,37,.94);
409
409
  background:var(--bg);padding:22px 20px;min-height:150px;
410
410
  display:flex;flex-direction:column;gap:10px;transition:background .35s;
411
411
  }
@@ -413,7 +413,7 @@ main{position:relative;z-index:2;padding-top:84px}
413
413
  .route-card h3{font-family:var(--display);font-weight:400;font-size:26px;display:flex;align-items:center;gap:10px}
414
414
  .route-card h3 img{width:20px;height:20px;border-radius:50%;object-fit:cover;background:rgba(255,255,255,.06)}
415
415
  .route-card .where{font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--blue)}
416
- .route-card p{color:#B7CCE0;font-size:15px;line-height:1.55}
416
+ .route-card p{color:#C9DAEC;font-size:15px;line-height:1.55}
417
417
  .route-card .chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:auto}
418
418
  .route-card.p-add{grid-column:1/-1;align-items:center;text-align:center;justify-content:center;gap:14px;padding:30px 22px}
419
419
  .route-card.p-add .chips{justify-content:center;margin-top:4px}
@@ -441,9 +441,9 @@ main{position:relative;z-index:2;padding-top:84px}
441
441
  .chain-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}
442
442
  .hl-surface{margin-top:34px;border:1px solid var(--line);border-radius:14px;padding:20px;background:rgba(124,196,255,.02)}
443
443
  .hl-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;margin-top:16px}
444
- .hl-grid article{border:1px solid var(--line);border-radius:10px;padding:14px 15px;background:rgba(255,255,255,.012)}
444
+ .hl-grid article{border:1px solid rgba(124,196,255,.22);border-radius:10px;padding:16px 17px;background:rgba(17,25,37,.92)}
445
445
  .hl-grid h3{font-family:var(--display);font-size:15px;font-weight:500;color:var(--ink);margin:0 0 6px}
446
- .hl-grid p{font-size:14px;line-height:1.6;color:#B7CCE0;margin:0}
446
+ .hl-grid p{font-size:14px;line-height:1.6;color:#C9DAEC;margin:0}
447
447
  .hl-note{margin:16px 0 0;font-family:var(--mono);font-size:10.5px;letter-spacing:.04em;color:var(--cool);opacity:.62}
448
448
  .hip3{margin-top:20px;padding-top:18px;border-top:1px solid var(--line)}
449
449
  .hl-note code{font-family:var(--mono);color:var(--blue2);opacity:.9}
@@ -451,7 +451,7 @@ main{position:relative;z-index:2;padding-top:84px}
451
451
  @media(max-width:620px){.hl-grid{grid-template-columns:1fr}}
452
452
  .chain{
453
453
  border:1px solid var(--line);border-radius:14px;padding:16px;
454
- background:linear-gradient(180deg, rgba(124,196,255,.035), transparent 55%), var(--panel);
454
+ background:linear-gradient(180deg, rgba(124,196,255,.06), transparent 55%), rgba(17,25,37,.94);
455
455
  min-height:100px;display:flex;flex-direction:column;justify-content:space-between;gap:12px;
456
456
  transition:border-color .3s,transform .3s var(--ease);
457
457
  }
@@ -468,6 +468,7 @@ main{position:relative;z-index:2;padding-top:84px}
468
468
  .badge.live{border-color:rgba(124,196,255,.35);color:var(--blue)}
469
469
 
470
470
  .venues{margin-top:14px;border:1px solid var(--line);border-radius:14px;overflow:hidden;background:rgba(17,25,37,.85)}
471
+ .venues{background:rgba(17,25,37,.86);border:1px solid rgba(124,196,255,.16);border-radius:16px;overflow:hidden;margin-bottom:14px}
471
472
  .venues-head{
472
473
  padding:11px 14px;border-bottom:1px solid var(--line);
473
474
  font-family:var(--mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--mute);
@@ -478,6 +479,7 @@ main{position:relative;z-index:2;padding-top:84px}
478
479
  .marquee + .marquee{border-top:1px solid rgba(124,196,255,.08)}
479
480
  .track{display:inline-flex;gap:26px;padding:12px 0;animation:scroll 48s linear infinite;will-change:transform}
480
481
  .marquee.rev .track{animation-direction:reverse;animation-duration:56s}
482
+ a.chip{text-decoration:none;color:inherit}
481
483
  .chip{
482
484
  display:inline-flex;align-items:center;gap:10px;
483
485
  font-size:15px;letter-spacing:-.015em;text-transform:none;color:var(--proto-color,var(--cool));
@@ -486,7 +488,7 @@ main{position:relative;z-index:2;padding-top:84px}
486
488
  }
487
489
  .chip img{width:18px;height:18px;border-radius:50%;object-fit:cover;background:rgba(255,255,255,.06)}
488
490
  .chip.wm-chip{padding:10px 16px}
489
- .chip img.wm{width:auto;height:20px;max-width:150px;border-radius:0;object-fit:contain;background:none;opacity:.92}
491
+ .chip img.wm{width:auto;height:20px;max-width:150px;border-radius:0;object-fit:contain;background:none;opacity:1}
490
492
  .chip img.wm.tall{height:22px;max-width:26px}
491
493
 
492
494
  .chip .wordmark{font-family:var(--proto-font,var(--sans));font-weight:var(--proto-weight,750);font-style:var(--proto-style,normal);text-transform:var(--proto-transform,none);letter-spacing:var(--proto-track,-.025em);line-height:1.2}
@@ -521,7 +523,7 @@ main{position:relative;z-index:2;padding-top:84px}
521
523
  margin-top:8px;
522
524
  }
523
525
  .wallet-card{
524
- background:var(--bg);padding:clamp(22px,3vw,30px);
526
+ background:rgba(17,25,37,.94);padding:clamp(22px,3vw,30px);
525
527
  display:flex;flex-direction:column;gap:12px;min-height:170px;
526
528
  transition:background .35s;
527
529
  }
@@ -634,7 +636,7 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
634
636
  <div class="home-inner">
635
637
  <div class="hero-stage">
636
638
  <div class="hero-art" aria-hidden="true">
637
- <video id="orb-vid" autoplay muted loop playsinline preload="metadata" poster="assets/hero/orb.avif">
639
+ <video id="orb-vid" muted loop playsinline preload="none" hidden>
638
640
  <source src="assets/hero/orb.webm" type="video/webm">
639
641
  </video>
640
642
  <div class="hero-orb" id="hero-orb">
@@ -742,7 +744,7 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
742
744
  <div class="tag">profile</div>
743
745
  <div class="name">robinhood agent</div>
744
746
  <div class="sub">markets · nfts · names</div>
745
- <div class="chains"><span class="ch">Robinhood Chain 4663 <img src="https://icons.llamao.fi/icons/chains/rsz_robinhood?w=24&h=24" alt="" loading="lazy"></span></div>
747
+ <div class="chains"><span class="ch">Robinhood Chain <img src="https://icons.llamao.fi/icons/chains/rsz_robinhood?w=24&h=24" alt="" loading="lazy"></span></div>
746
748
  </div>
747
749
  <div class="node route p-sol">
748
750
  <div class="tag">profile</div>
@@ -825,11 +827,11 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
825
827
  <article class="route-card p-rh">
826
828
  <div class="where">robinhood agent →</div>
827
829
  <h3>Robinhood <img src="https://icons.llamao.fi/icons/chains/rsz_robinhood?w=40&h=40" alt="Robinhood Chain" loading="lazy"></h3>
828
- <p>RH Chain markets, NFTs, names, token scans, and chain-local routing on 4663.</p>
830
+ <p>RH Chain markets, NFTs, names, token scans, and chain-local routing.</p>
829
831
  <div class="chips">
830
832
  <span class="chip-s">markets</span>
831
833
  <span class="chip-s">NFTs</span>
832
- <span class="chip-s">4663</span>
834
+ <span class="chip-s">rh chain</span>
833
835
  </div>
834
836
  </article>
835
837
  <article class="route-card p-sol">
@@ -875,10 +877,10 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
875
877
  <article class="route-card p-stable">
876
878
  <div class="where">stable agent →</div>
877
879
  <h3>Stable <img src="https://icons.llamao.fi/icons/chains/rsz_stable?w=40&h=40" alt="Stable" loading="lazy"></h3>
878
- <p>Stable mainnet launch radar and venue ops on chain 988, scanned straight from the chain's own logs.</p>
880
+ <p>Stable mainnet launch radar and venue ops, scanned straight from the chain's own logs.</p>
879
881
  <div class="chips">
880
882
  <span class="chip-s">launches</span>
881
- <span class="chip-s">Stable 988</span>
883
+ <span class="chip-s">Stable</span>
882
884
  </div>
883
885
  </article>
884
886
  <article class="route-card p-build">
@@ -980,17 +982,17 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
980
982
  <article><h3>Staking</h3><p>Validator summaries, delegations, rewards and history. Stake deposit, withdraw and delegate prepare with a 7-day unstaking queue.</p></article>
981
983
  <article><h3>Outcome markets</h3><p>HIP-4 outcome listing plus order and cancel prepare.</p></article>
982
984
  <article><h3>Account state</h3><p>Clearinghouse state, open orders, user fills, positions.</p></article>
983
- <article><h3>HyperEVM 999</h3><p>Token search and metadata on chain 999, routed with the EVM lane.</p></article>
985
+ <article><h3>HyperEVM</h3><p>Token search and metadata on Hyperliquid, routed with the EVM lane.</p></article>
984
986
  </div>
985
987
  </div>
986
988
  <div class="venues rv">
987
989
  <div class="venues-head"><span>protocols // venues</span><span><b>routed by name</b> · quotes ranked · prepare-only</span></div>
988
- <div class="marquee" aria-hidden="true"><div class="track" id="proto-track-a"></div></div>
989
- <div class="marquee rev" aria-hidden="true"><div class="track" id="proto-track-b"></div></div>
990
+ <div class="marquee"><div class="track" id="proto-track-a"></div></div>
991
+ <div class="marquee rev"><div class="track" id="proto-track-b"></div></div>
990
992
  </div>
991
993
  <div class="venues rv">
992
994
  <div class="venues-head"><span>models // harnesses</span><span><b>bring your own model</b> · oracle is the control plane</span></div>
993
- <div class="marquee" aria-hidden="true"><div class="track" id="llm-track"></div></div>
995
+ <div class="marquee"><div class="track" id="llm-track"></div></div>
994
996
  </div>
995
997
  </section>
996
998
 
@@ -1022,7 +1024,7 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
1022
1024
  </div>
1023
1025
  <div class="foot-meta">
1024
1026
  <span>oracle · <a class="labs-link" href="https://demi.la">locals only labs</a></span>
1025
- <span>you sign // no house custody</span>
1027
+ <span>self custodial // the future is agentic</span>
1026
1028
  </div>
1027
1029
  </footer>
1028
1030
 
@@ -1051,53 +1053,53 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
1051
1053
  var cls = c.badge === "live" ? "badge live" : "badge";
1052
1054
  var label = c.badge === "live" ? "live" : "read";
1053
1055
  return '<article class="chain rv"><div class="chain-top"><div class="nm">' + c.name +
1054
- ' <img src="' + ICON + c.logo + '?w=36&h=36" alt="' + c.name + ' logo" loading="lazy"></div><div class="id">' + c.id +
1055
- '</div></div><div class="meta"><span>' + c.note + '</span><span class="' + cls + '">' + label + '</span></div></article>';
1056
+ ' <img src="' + ICON + c.logo + '?w=36&h=36" alt="' + c.name + ' logo" loading="lazy"></div></div><div class="meta"><span>' + c.note + '</span><span class="' + cls + '">' + label + '</span></div></article>';
1056
1057
  }).join("");
1057
1058
 
1058
1059
  var WM = "assets/wordmarks/";
1059
1060
  var PROTOS_A = [
1060
- { n: "Hyperliquid", wm: "hyperliquid.svg" },
1061
- { n: "Outcome", wm: "outcome.svg" },
1062
- { n: "XYZ", wm: "xyz.svg" },
1063
- { n: "Markets By Kinetiq", txt: 1 },
1064
- { n: "HyENA", wm: "hyena.svg" },
1065
- { n: "Paragon", txt: 1 },
1066
- { n: "HyperSwap", wm: "hyperswap.svg" },
1067
- { n: "Uniswap", wm: "uniswap.svg" },
1068
- { n: "Polymarket", wm: "polymarket.png" },
1069
- { n: "Aerodrome", wm: "aerodrome.svg" },
1070
- { n: "Velodrome", wm: "velodrome.svg" },
1071
- { n: "PancakeSwap", wm: "pancakeswap.svg" },
1072
- { n: "QuickSwap", wm: "quickswap.png" },
1073
- { n: "LFJ", txt: 1 },
1074
- { n: "Curve", txt: 1 },
1075
- { n: "Balancer", wm: "balancer.svg" },
1076
- { n: "Pendle", wm: "pendle.png" }
1061
+ { n: "Hyperliquid", wm: "hyperliquid.svg", u: "https://hyperliquid.xyz" },
1062
+ { n: "Outcome", wm: "outcome.svg", u: "https://outcome.xyz" },
1063
+ { n: "XYZ", wm: "xyz.svg", u: "https://trade.xyz" },
1064
+ { n: "Markets By Kinetiq", wm: "kinetiq.svg", tall: 1, u: "https://kinetiq.xyz" },
1065
+ { n: "HyENA", wm: "hyena.svg", u: "https://hyena.trade" },
1066
+ { n: "Paragon", wm: "paragon.svg", tall: 1, u: "https://paragon.trade" },
1067
+ { n: "HyperSwap", wm: "hyperswap.svg", u: "https://hyperswap.exchange" },
1068
+ { n: "Uniswap", wm: "uniswap.svg", u: "https://uniswap.org" },
1069
+ { n: "Polymarket", wm: "polymarket.png", u: "https://polymarket.com" },
1070
+ { n: "Aerodrome", wm: "aerodrome.svg", u: "https://aerodrome.finance" },
1071
+ { n: "Velodrome", wm: "velodrome.svg", u: "https://velodrome.finance" },
1072
+ { n: "PancakeSwap", wm: "pancakeswap.svg", u: "https://pancakeswap.finance" },
1073
+ { n: "QuickSwap", wm: "quickswap.png", u: "https://quickswap.exchange" },
1074
+ { n: "LFJ", wm: "lfj.webp", tall: 1, u: "https://lfj.gg" },
1075
+ { n: "Curve", wm: "curve.png", tall: 1, u: "https://curve.finance" },
1076
+ { n: "Balancer", wm: "balancer.svg", u: "https://balancer.fi" },
1077
+ { n: "Pendle", wm: "pendle.png", u: "https://pendle.finance" }
1077
1078
  ];
1078
1079
  var PROTOS_B = [
1079
- { n: "Morpho", wm: "morpho.svg" },
1080
- { n: "GMX", wm: "gmx.svg" },
1081
- { n: "LI.FI", wm: "lifi.png" },
1082
- { n: "Relay", wm: "relay.svg" },
1083
- { n: "Velora", wm: "paraswap.svg" },
1084
- { n: "Odos", wm: "odos.svg" },
1085
- { n: "CoW Swap", wm: "cowswap.svg" },
1086
- { n: "1inch", wm: "oneinch.svg" },
1087
- { n: "Jupiter", wm: "jupiter.svg" },
1088
- { n: "OpenSea", wm: "opensea.svg" },
1089
- { n: "Across", wm: "across.svg" },
1090
- { n: "Stargate", wm: "stargate.svg" },
1091
- { n: "Magic Eden", wm: "magic-eden.svg" }
1080
+ { n: "Morpho", wm: "morpho.svg", u: "https://morpho.org" },
1081
+ { n: "GMX", wm: "gmx.svg", u: "https://gmx.io" },
1082
+ { n: "LI.FI", wm: "lifi.png", u: "https://li.fi" },
1083
+ { n: "Relay", wm: "relay.svg", u: "https://relay.link" },
1084
+ { n: "Velora", wm: "paraswap.svg", u: "https://velora.xyz" },
1085
+ { n: "Odos", wm: "odos.svg", u: "https://odos.xyz" },
1086
+ { n: "CoW Swap", wm: "cowswap.svg", u: "https://cow.fi" },
1087
+ { n: "1inch", wm: "oneinch.svg", u: "https://1inch.io" },
1088
+ { n: "Jupiter", wm: "jupiter.svg", u: "https://jup.ag" },
1089
+ { n: "OpenSea", wm: "opensea.svg", u: "https://opensea.io" },
1090
+ { n: "Across", wm: "across.svg", u: "https://across.to" },
1091
+ { n: "Stargate", wm: "stargate.svg", u: "https://stargate.finance" },
1092
+ { n: "Magic Eden", wm: "magic-eden.svg", u: "https://magiceden.io" }
1092
1093
  ];
1093
1094
 
1094
1095
  function chipRow(list) {
1095
1096
  var seq = list.concat(list);
1096
1097
  return seq.map(function (x) {
1097
- if (x.wm) {
1098
- return '<span class="chip wm-chip"><img class="wm" src="' + WM + x.wm + '" alt="' + x.n + '" decoding="async"></span>';
1099
- }
1100
- return '<span class="chip wm-chip"><span class="wordmark">' + x.n + '</span></span>';
1098
+ var body = x.wm
1099
+ ? '<img class="' + (x.tall ? 'wm tall' : 'wm') + '" src="' + WM + x.wm + '" alt="' + x.n + '" decoding="async">' +
1100
+ (x.tall ? '<span class="wordmark">' + x.n + '</span>' : '')
1101
+ : '<span class="wordmark">' + x.n + '</span>';
1102
+ return '<a class="chip wm-chip" href="' + x.u + '" target="_blank" rel="noopener noreferrer" aria-label="' + x.n + '">' + body + '</a>';
1101
1103
  }).join("");
1102
1104
  }
1103
1105
  document.getElementById("proto-track-a").innerHTML = chipRow(PROTOS_A);
@@ -1105,23 +1107,23 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
1105
1107
 
1106
1108
  var LM = "assets/llms/";
1107
1109
  var LLMS = [
1108
- { n: "Hermes Agent", wm: "hermes.png", tall: 1 },
1109
- { n: "Claude", wm: "claude.svg" },
1110
- { n: "Grok", wm: "grok.svg" },
1111
- { n: "Codex", wm: "codex.svg" },
1112
- { n: "Gemini", wm: "gemini.svg" },
1113
- { n: "OpenClaw", wm: "openclaw.svg", tall: 1 },
1114
- { n: "Perplexity", wm: "perplexity.svg" },
1115
- { n: "Manus", wm: "manus.svg" },
1116
- { n: "Cursor", wm: "cursor.svg" },
1117
- { n: "Windsurf", wm: "windsurf.svg" },
1118
- { n: "DeepSeek", wm: "deepseek.svg" },
1119
- { n: "Qwen", wm: "qwen.svg", tall: 1 },
1120
- { n: "Kimi", wm: "kimi.svg" }
1110
+ { n: "Hermes Agent", wm: "hermes.png", tall: 1, u: "https://hermes.nousresearch.com" },
1111
+ { n: "Claude", wm: "claude.svg", u: "https://claude.ai" },
1112
+ { n: "Grok", wm: "grok.svg", u: "https://grok.com" },
1113
+ { n: "Codex", wm: "codex.svg", u: "https://openai.com/codex" },
1114
+ { n: "Gemini", wm: "gemini.svg", u: "https://gemini.google.com" },
1115
+ { n: "OpenClaw", wm: "openclaw.svg", tall: 1, u: "https://openclaw.ai" },
1116
+ { n: "Perplexity", wm: "perplexity.svg", u: "https://perplexity.ai" },
1117
+ { n: "Manus", wm: "manus.svg", u: "https://manus.im" },
1118
+ { n: "Cursor", wm: "cursor-icon.svg", tall: 1, u: "https://cursor.com" },
1119
+ { n: "Windsurf", wm: "windsurf.svg", u: "https://windsurf.com" },
1120
+ { n: "DeepSeek", wm: "deepseek.svg", u: "https://deepseek.com" },
1121
+ { n: "Qwen", wm: "qwen.svg", tall: 1, u: "https://chat.qwen.ai" },
1122
+ { n: "Kimi", wm: "kimi-icon.svg", tall: 1, u: "https://kimi.com" }
1121
1123
  ];
1122
1124
  document.getElementById("llm-track").innerHTML = LLMS.concat(LLMS).map(function (x) {
1123
1125
  var cls = x.tall ? "wm tall" : "wm";
1124
- return '<span class="chip wm-chip"><img class="' + cls + '" src="' + LM + x.wm + '" alt="' + x.n + '" decoding="async">' + (x.tall ? '<span class="wordmark">' + x.n + '</span>' : '') + '</span>';
1126
+ return '<a class="chip wm-chip" href="' + x.u + '" target="_blank" rel="noopener noreferrer" aria-label="' + x.n + '"><img class="' + cls + '" src="' + LM + x.wm + '" alt="' + x.n + '" decoding="async">' + (x.tall ? '<span class="wordmark">' + x.n + '</span>' : '') + '</a>';
1125
1127
  }).join("");
1126
1128
 
1127
1129
  var loader = document.getElementById("loader");
@@ -1171,19 +1173,7 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
1171
1173
  }, { passive: true });
1172
1174
  }
1173
1175
 
1174
- (function () {
1175
- var v = document.getElementById("orb-vid");
1176
- if (!v) return;
1177
- var art = document.querySelector(".hero-art");
1178
- function ready() { art.classList.add("blender-orb"); v.classList.add("ready"); }
1179
- if (v.readyState >= 2) ready();
1180
- v.addEventListener("loadeddata", ready, { once: true });
1181
- if (reduced) { v.removeAttribute("autoplay"); v.pause(); ready(); return; }
1182
- document.addEventListener("visibilitychange", function () {
1183
- if (document.visibilityState === "visible") { var q = v.play(); if (q && q.catch) q.catch(function () {}); }
1184
- else v.pause();
1185
- });
1186
- })();
1176
+ // Hero is the original CSS orb.
1187
1177
 
1188
1178
  var nodes = Array.prototype.slice.call(document.querySelectorAll(".rv, .wires"));
1189
1179
  if (reduced || !("IntersectionObserver" in window)) {
@@ -526,3 +526,14 @@ registerProvider({
526
526
  baseEnv: ["PARASWAP_API_URL"],
527
527
  description: "ParaSwap/Velora public price routes + validated transaction builder",
528
528
  });
529
+
530
+ registerProvider({
531
+ id: "rfq",
532
+ venue: "intent-rfq",
533
+ chainIds: [1, 10, 56, 137, 8453, 42161, 43114],
534
+ auth: "none",
535
+ ops: ["health", "intent", "quote"],
536
+ execution: "prepare",
537
+ baseEnv: ["ZEROX_API_KEY", "ONEINCH_API_KEY"],
538
+ description: "Cross-chain RFQ intent normalizer and firm-quote fanout over reviewed venues. Prepares artifacts only, never signs or broadcasts.",
539
+ });
@@ -44,6 +44,7 @@ import * as portfolio from "./providers/portfolio.mjs";
44
44
  import * as portfolioHistory from "./providers/portfolio-history.mjs";
45
45
  import * as nftPortfolio from "./providers/nft-portfolio.mjs";
46
46
  import * as paraswap from "./providers/paraswap.mjs";
47
+ import * as rfq from "./providers/rfq.mjs";
47
48
 
48
49
  const OPS = {
49
50
  "hl-info": {
@@ -356,6 +357,11 @@ const OPS = {
356
357
  quote: (o, a = {}) => paraswap.paraswapPrice(a, o),
357
358
  prepare: (o, a = {}) => paraswap.paraswapPrepare(a, o),
358
359
  },
360
+ rfq: {
361
+ health: (o) => rfq.rfqHealth(o),
362
+ intent: (o, a = {}) => rfq.rfqIntent(a, o),
363
+ quote: (o, a = {}) => rfq.rfqQuote(a, o),
364
+ },
359
365
  };
360
366
 
361
367
  /**
@@ -0,0 +1,15 @@
1
+ import { normalizeRfqIntent } from "../../rfq/intent.mjs";
2
+ import { requestRfqQuotes } from "../../rfq/sources.mjs";
3
+
4
+ export function rfqIntent(args = {}, opts = {}) {
5
+ return normalizeRfqIntent(args, opts);
6
+ }
7
+
8
+ export async function rfqQuote(args = {}, opts = {}) {
9
+ const intent = args.intent?.kind === "rfq-intent" ? args.intent : normalizeRfqIntent(args, opts);
10
+ return requestRfqQuotes(intent, opts);
11
+ }
12
+
13
+ export async function rfqHealth() {
14
+ return { ok: true, provider: "rfq", mode: "intent-rfq", execution: "prepare" };
15
+ }
package/src/index.mjs CHANGED
@@ -38,6 +38,13 @@ export {
38
38
  } from "./scanner/index.mjs";
39
39
 
40
40
  export { bestSwapRoute, bestBridgeRoute, QUALITY } from "./router/index.mjs";
41
+ export {
42
+ normalizeRfqIntent,
43
+ normalizeFirmQuote,
44
+ hashRfqIntent,
45
+ hashFirmQuote,
46
+ } from "./rfq/intent.mjs";
47
+ export { sourceCandidates, executeRfqCandidates, rankRfqQuotes, requestRfqQuotes } from "./rfq/sources.mjs";
41
48
  export { validateNftMintGasWar, assertNftMintGasWar, NftGasWarLimitError } from "./nft-gas-war-guard.mjs";
42
49
  export { simulateSell, assertSellable, SELL_SIM } from "./sell-simulation.mjs";
43
50
  export { capabilityStatus, assertCapability, autonomousTradingEnabled, posture } from "./capability-posture.mjs";
@@ -0,0 +1,180 @@
1
+ import { createHash } from "node:crypto";
2
+ import { getAddress, isAddress } from "ethers";
3
+
4
+ export const NATIVE_TOKEN = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
5
+ export const DEFAULT_SAME_CHAIN_SOURCES = Object.freeze(["lifi", "paraswap", "0x", "cow", "uniswap-v3"]);
6
+ export const DEFAULT_CROSS_CHAIN_SOURCES = Object.freeze(["lifi"]);
7
+ const HEX32 = /^0x[0-9a-fA-F]{64}$/;
8
+ const INT = /^\d+$/;
9
+
10
+ function fail(label, message = "invalid") {
11
+ throw new Error(`rfq: ${label} ${message}`);
12
+ }
13
+
14
+ function chainId(value, label) {
15
+ const n = Number(value);
16
+ if (!Number.isSafeInteger(n) || n <= 0) fail(label, "must be a positive chainId");
17
+ return n;
18
+ }
19
+
20
+ function amount(value, label) {
21
+ const s = String(value ?? "").trim();
22
+ if (!INT.test(s) || BigInt(s) <= 0n) fail(label, "must be a positive integer string");
23
+ return s;
24
+ }
25
+
26
+ function optionalAmount(value, label) {
27
+ if (value == null || value === "") return null;
28
+ return amount(value, label);
29
+ }
30
+
31
+ function token(value, label) {
32
+ const s = String(value ?? "").trim();
33
+ if (s.toLowerCase() === NATIVE_TOKEN.toLowerCase()) return NATIVE_TOKEN;
34
+ if (!isAddress(s)) fail(label, "must be an EVM address or native token sentinel");
35
+ return getAddress(s);
36
+ }
37
+
38
+ function address(value, label) {
39
+ const s = String(value ?? "").trim();
40
+ if (!isAddress(s)) fail(label, "must be an EVM address");
41
+ return getAddress(s);
42
+ }
43
+
44
+ function optionalAddress(value, label) {
45
+ if (value == null || value === "") return null;
46
+ return address(value, label);
47
+ }
48
+
49
+ function stringList(value, label, defaults) {
50
+ if (value === undefined) return [...defaults];
51
+ if (!Array.isArray(value)) fail(label, "must be an array");
52
+ return value.map((x) => String(x).trim()).filter(Boolean);
53
+ }
54
+
55
+ function deadline(value, { nowMs, maxDeadlineMs }, label) {
56
+ const n = Number(value);
57
+ if (!Number.isFinite(n)) fail(label, "must be a finite millisecond timestamp");
58
+ if (n <= nowMs) fail(label, "expired");
59
+ if (n > nowMs + maxDeadlineMs) fail(label, "exceeds maxDeadlineMs");
60
+ return Math.floor(n);
61
+ }
62
+
63
+ function plain(value) {
64
+ if (Array.isArray(value)) return value.map(plain);
65
+ if (value && typeof value === "object") {
66
+ const out = {};
67
+ for (const key of Object.keys(value).sort()) {
68
+ if (value[key] !== undefined) out[key] = plain(value[key]);
69
+ }
70
+ return out;
71
+ }
72
+ return value;
73
+ }
74
+
75
+ export function canonicalJson(value) {
76
+ return JSON.stringify(plain(value));
77
+ }
78
+
79
+ export function sha256Hex(value) {
80
+ return `0x${createHash("sha256").update(canonicalJson(value)).digest("hex")}`;
81
+ }
82
+
83
+ function withoutHash(value, keys) {
84
+ const out = { ...value };
85
+ for (const key of keys) delete out[key];
86
+ return out;
87
+ }
88
+
89
+ export function hashRfqIntent(intent) {
90
+ return sha256Hex(withoutHash(intent, ["intentHash"]));
91
+ }
92
+
93
+ export function hashFirmQuote(quote) {
94
+ return sha256Hex(withoutHash(quote, ["firmQuoteHash"]));
95
+ }
96
+
97
+ export function normalizeRfqIntent(input = {}, opts = {}) {
98
+ const nowMs = Number(opts.nowMs ?? Date.now());
99
+ const maxDeadlineMs = Number(opts.maxDeadlineMs ?? 30 * 60 * 1000);
100
+ if (!Number.isFinite(nowMs) || !Number.isFinite(maxDeadlineMs) || maxDeadlineMs <= 0) fail("time", "is invalid");
101
+ const fromChainId = chainId(input.fromChainId ?? input.fromChain, "fromChainId");
102
+ const toChainId = chainId(input.toChainId ?? input.toChain, "toChainId");
103
+ const sameChain = fromChainId === toChainId;
104
+ const defaults = sameChain ? DEFAULT_SAME_CHAIN_SOURCES : DEFAULT_CROSS_CHAIN_SOURCES;
105
+ const intent = {
106
+ kind: "rfq-intent",
107
+ version: 1,
108
+ fromChainId,
109
+ toChainId,
110
+ sellToken: token(input.sellToken ?? input.tokenIn ?? input.fromToken, "sellToken"),
111
+ buyToken: token(input.buyToken ?? input.tokenOut ?? input.toToken, "buyToken"),
112
+ sellAmount: amount(input.sellAmount ?? input.amountIn ?? input.fromAmount, "sellAmount"),
113
+ receiver: address(input.receiver ?? input.recipient ?? input.to, "receiver"),
114
+ deadlineMs: deadline(input.deadlineMs ?? input.deadline ?? input.expiresAtMs, { nowMs, maxDeadlineMs }, "deadline"),
115
+ minBuyAmount: optionalAmount(input.minBuyAmount ?? input.minOut ?? input.amountOutMin, "minBuyAmount"),
116
+ allowedSources: stringList(input.allowedSources, "allowedSources", defaults),
117
+ allowedRouters: stringList(input.allowedRouters, "allowedRouters", []),
118
+ slippageBps: Number.isFinite(Number(input.slippageBps)) ? Number(input.slippageBps) : null,
119
+ partialFill: input.partialFill === true,
120
+ metadata: input.metadata && typeof input.metadata === "object" && !Array.isArray(input.metadata) ? plain(input.metadata) : {},
121
+ };
122
+ if (intent.slippageBps != null && (!Number.isInteger(intent.slippageBps) || intent.slippageBps < 0 || intent.slippageBps > 10_000)) fail("slippageBps", "must be 0 to 10000");
123
+ intent.intentId = input.intentId ? String(input.intentId) : sha256Hex({ seed: "rfq-intent", intent }).slice(0, 34);
124
+ intent.intentHash = hashRfqIntent(intent);
125
+ return Object.freeze(intent);
126
+ }
127
+
128
+ function artifact(value) {
129
+ if (!value || typeof value !== "object" || Array.isArray(value)) fail("artifact", "required");
130
+ if (value.typedDataHash != null && !HEX32.test(String(value.typedDataHash))) fail("artifact.typedDataHash", "must be bytes32");
131
+ if (value.calldataHash != null && !HEX32.test(String(value.calldataHash))) fail("artifact.calldataHash", "must be bytes32");
132
+ if (value.to != null && !isAddress(String(value.to))) fail("artifact.to", "must be an address");
133
+ if (value.data != null && !/^0x(?:[0-9a-fA-F]{2})*$/.test(String(value.data))) fail("artifact.data", "must be hex");
134
+ return plain(value);
135
+ }
136
+
137
+ export function normalizeFirmQuote(intent, quote = {}, opts = {}) {
138
+ if (!intent || intent.kind !== "rfq-intent") fail("intent", "required");
139
+ const nowMs = Number(opts.nowMs ?? Date.now());
140
+ const expiryMs = Number(quote.expiryMs ?? quote.expiresAtMs ?? quote.validUntilMs);
141
+ if (!Number.isFinite(expiryMs)) fail("quote expiry", "required");
142
+ if (expiryMs <= nowMs) fail("quote", "expired");
143
+ if (expiryMs > intent.deadlineMs) fail("quote expiry", "exceeds intent deadline");
144
+ const source = String(quote.source ?? quote.provider ?? "").trim();
145
+ if (!source) fail("source", "required");
146
+ if (!intent.allowedSources.includes(source)) fail("source", "not allowed by intent");
147
+ const amountOut = amount(quote.amountOut ?? quote.buyAmount, "amountOut");
148
+ const minBuyAmount = amount(quote.minBuyAmount ?? quote.minOut ?? amountOut, "minBuyAmount");
149
+ if (BigInt(minBuyAmount) > BigInt(amountOut)) fail("minBuyAmount", "exceeds amountOut");
150
+ const artifactValue = artifact(quote.artifact ?? quote.executableArtifact ?? quote.transaction ?? quote.typedData);
151
+ const quotedAtMs = Number(quote.quotedAtMs ?? quote.timestampMs ?? opts.nowMs ?? Date.now());
152
+ if (!Number.isFinite(quotedAtMs)) fail("quotedAtMs", "must be finite");
153
+ const router = optionalAddress(quote.router ?? quote.settlementRouter ?? artifactValue.to, "router");
154
+ const out = {
155
+ kind: "rfq-firm-quote",
156
+ provider: "rfq",
157
+ surface: "rfq",
158
+ version: 1,
159
+ quoteId: String(quote.quoteId ?? quote.id ?? "").trim(),
160
+ source,
161
+ intentHash: intent.intentHash,
162
+ fromChainId: intent.fromChainId,
163
+ toChainId: intent.toChainId,
164
+ sellToken: intent.sellToken,
165
+ buyToken: intent.buyToken,
166
+ sellAmount: intent.sellAmount,
167
+ receiver: intent.receiver,
168
+ router,
169
+ amountOut,
170
+ minBuyAmount,
171
+ quotedAtMs: Math.floor(quotedAtMs),
172
+ expiryMs: Math.floor(expiryMs),
173
+ artifact: artifactValue,
174
+ maker: quote.maker ? String(quote.maker) : null,
175
+ metadata: quote.metadata && typeof quote.metadata === "object" && !Array.isArray(quote.metadata) ? plain(quote.metadata) : {},
176
+ };
177
+ if (!out.quoteId) out.quoteId = sha256Hex({ seed: "rfq-quote", out }).slice(0, 34);
178
+ out.firmQuoteHash = hashFirmQuote(out);
179
+ return Object.freeze(out);
180
+ }