Skip to content

Add Gami Labs yield adapter#2715

Open
marien-gami wants to merge 3 commits into
DefiLlama:masterfrom
marien-gami:add-gami-labs-yields
Open

Add Gami Labs yield adapter#2715
marien-gami wants to merge 3 commits into
DefiLlama:masterfrom
marien-gami:add-gami-labs-yields

Conversation

@marien-gami
Copy link
Copy Markdown

@marien-gami marien-gami commented May 29, 2026

Yield adapter - Gami Labs

This PR adds a yield adapter for Gami Labs, listed on TVL via DefiLlama/DefiLlama-Adapters#19461 (merged).

Methodology

Reports pricePerShare (= totalAssets / totalSupply, ratio of underlying per share) for each curated vault. DefiLlama yield-server will compute apyBase from the daily PPS deltas. No reward APY (Gami curator vaults have no liquidity mining).

Coverage

  • 15 vaults across 5 chains: Ethereum, Base, Flare, Hemi, Avalanche
  • Protocols: Lagoon (ERC-7540), Spectra MetaVault, Silo Vaults V2, Gearbox V3 Pool
  • All vaults are ERC-4626 compatible - adapter uses standard asset(), totalAssets(), totalSupply(), decimals(), symbol(), convertToAssets().

Local test

Adapter outputs 15 pools, total TVL ~$24M (matches DefiLlama TVL page).

Notes

  • 2 vaults have TVL below the $10k display threshold (Hemi USDC at $1 seed, Silo AVAX at $898). They'll appear in the adapter output but be filtered out from /yields display - expected behavior per yield-server README.
  • No external API dependencies - adapter uses on-chain calls via @defillama/sdk and DefiLlama's own price feed (coins.llama.fi).

Summary by CodeRabbit

  • New Features
    • Added support for Gami Labs vaults across multiple blockchains, exposing per-vault TVL in USD, underlying asset prices, and price-per-share metrics.
    • API now aggregates per-chain vault data and returns flattened results with metadata and a link to the Gami Labs site.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0e2fed8d-6e38-444f-9d76-f2e9d66b6b92

📥 Commits

Reviewing files that changed from the base of the PR and between 9624aa9 and e32bfd3.

📒 Files selected for processing (1)
  • src/adaptors/gami-labs/index.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/adaptors/gami-labs/index.js

📝 Walkthrough

Walkthrough

Adds a new Gami Labs adaptor that registers vaults, gathers vault state via batched multicalls, fetches USD prices for underlyings from Llama, computes normalized tvlUsd and pricePerShare per vault, and exports an apy function with metadata (timetravel: false, url).

Changes

Gami Labs Adaptor

Layer / File(s) Summary
Vault registry and ABI contracts
src/adaptors/gami-labs/index.js (lines 1–36)
Defines the canonical vault registry by chain/address, maps chain display names, and declares the minimal ABI selectors (asset, totalAssets, decimals, symbol, convertToAssets).
Helpers: HTTP and multicall
src/adaptors/gami-labs/index.js (lines 38–47)
Adds fetchJson for external HTTP requests and multi wrapper that runs batched ABI calls via @defillama/sdk with permitFailure: true.
On-chain pipeline and metric computation
src/adaptors/gami-labs/index.js (lines 49–105)
Implements processChain to perform multicalls for vault fields, determine underlying decimals, fetch Llama USD prices for discovered assets, filter incomplete entries, and compute normalized tvlUsd and pricePerShare.
APY export and adaptor metadata
src/adaptors/gami-labs/index.js (lines 107–124)
Groups VAULTS by sdkChain, runs processChain concurrently per chain, flattens pool objects, and exports module.exports = { timetravel: false, apy, url }.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • 0xkr3p

Poem

A rabbit sniffs the vaults beneath the moon, 🐇
Multicalls hum, prices sing a tune,
Assets counted, decimals kept in line,
TVL and shares now measured fine,
A little hop — the adaptor's live and bright.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add Gami Labs yield adapter' directly and clearly summarizes the main change—adding a yield adapter for Gami Labs. It is concise, specific, and accurately reflects the changeset's primary purpose.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

Error while running gami-labs adapter:

Test Suites: 1 failed, 1 total
Tests: 16 failed, 108 passed, 124 total
Snapshots: 0 total
Time: 0.356 s
Ran all test suites.

Nb of pools: 15
 

Sample pools:
┌─────────┬───────────────────────────────────────────────────────┬─────────────┬─────────────┬─────────────┬────────────────────┬───────────────┬──────────────────────────────────────────────────┬────────────────────────────┬───────────────────────────────────────────────────────────────────────────────┐
│ (index) │ pool                                                  │ chain       │ project     │ symbol      │ tvlUsd             │ pricePerShare │ underlyingTokens                                 │ poolMeta                   │ url                                                                           │
├─────────┼───────────────────────────────────────────────────────┼─────────────┼─────────────┼─────────────┼────────────────────┼───────────────┼──────────────────────────────────────────────────┼────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ 0       │ '0x776f95321a0285f8bcde149e3264d16dc08da69a-base'     │ 'Base'      │ 'gami-labs' │ 'gamisUSDC' │ 4530521.563345297  │ 1.024141      │ [ '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' ] │ 'Gami Spectra USDC'        │ 'https://gamilabs.io/vaults/8453/0x5e93e1193a5e297cba0856e9b3f22b6e05429b9a'  │
│ 1       │ '0x6420a613e936602ca3f1ad5680b3f4d47d473bf1-flare'    │ 'Flare'     │ 'gami-labs' │ 'gamisXRP'  │ 4224371.187218211  │ 1.000363      │ [ '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │ 'Flare XRP Yield Prime'    │ 'https://gamilabs.io/vaults/14/0x0c4f32c53d4b91a019c7c9d8da14af140295eef6'    │
│ 2       │ '0x2a676c2744421b4fae65ce86b47adacb620047d4-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'ghemiBTC'  │ 3805328.8761515184 │ 1.0111261     │ [ '0x06ea695b91700071b161a434fed42d1dcbad9f00' ] │ 'Gami hemiBTC'             │ 'https://gamilabs.io/vaults/1/0x2a676c2744421b4fae65ce86b47adacb620047d4'     │
│ 3       │ '0x57e6824a8b15b709cefb4ccef644ba1349057e77-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'xBTCY'     │ 3719842.9448438464 │ 1             │ [ '0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf' ] │ 'xBTCY'                    │ 'https://gamilabs.io/vaults/1/0x57e6824a8b15b709cefb4ccef644ba1349057e77'     │
│ 4       │ '0xdae854d0896ad2fee335689a3f7b4a95fd1a3e46-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'gamiusdc'  │ 2711987.1076811673 │ 1.060237      │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Gami USDC'                │ 'https://gamilabs.io/vaults/1/0xdae854d0896ad2fee335689a3f7b4a95fd1a3e46'     │
│ 5       │ '0x1f0570a081fee0e4df6eac470f9d2d53cdeda1c5-avax'     │ 'Avalanche' │ 'gami-labs' │ 'USDC'      │ 1229092.5217374929 │ 0.000001      │ [ '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e' ] │ 'Gami Silo USDC'           │ 'https://gamilabs.io/vaults/43114/0x1F0570a081FeE0e4dF6eAC470f9d2D53CDEDa1c5' │
│ 6       │ '0xb3a2bcb30c1460d88db18b42a29fae2399952874-avax'     │ 'Avalanche' │ 'gami-labs' │ 'agUSDC'    │ 1018968.6696973606 │ 1.015863      │ [ '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e' ] │ 'USDC Avalanche Core'      │ 'https://gamilabs.io/vaults/43114/0xb3a2bcb30c1460d88db18b42a29fae2399952874' │
│ 7       │ '0xfab0f56c28e3f874b15922b213e696f37b670916-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'gamicUSPC' │ 995256.1293397367  │ 1.019789      │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Coinshift USPC Prime'     │ 'https://gamilabs.io/vaults/1/0xfab0f56c28e3f874b15922b213e696f37b670916'     │
│ 8       │ '0x414070fb9e64fd69160d75da57e75ba11f9f605a-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'gamiWBTC'  │ 608539.7730546611  │ 1.02597055    │ [ '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599' ] │ 'Gami WBTC'                │ 'https://gamilabs.io/vaults/1/0x414070fb9e64fd69160d75da57e75ba11f9f605a'     │
│ 9       │ '0x09252d2c4afca9b1479efdd39faa53de9ff23114-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'gamilUSPC' │ 501349.64404203277 │ 1.002458      │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Coinshift Leveraged USPC' │ 'https://gamilabs.io/vaults/1/0x09252d2c4afca9b1479efdd39faa53de9ff23114'     │
└─────────┴───────────────────────────────────────────────────────┴─────────────┴─────────────┴─────────────┴────────────────────┴───────────────┴──────────────────────────────────────────────────┴────────────────────────────┴───────────────────────────────────────────────────────────────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/adaptors/gami-labs/index.js (1)

121-123: ⚡ Quick win

One failing chain drops every pool.

Promise.all rejects as soon as any processChain throws (e.g. an sdk.api.abi.multiCall error on one chain or the price fetch failing), so a single-chain hiccup yields zero pools instead of partial results. Consider isolating per-chain failures.

♻️ Isolate per-chain failures
-  const results = await Promise.all(
-    Object.entries(byChain).map(([chain, vaults]) => processChain(chain, vaults))
-  );
-
-  return results.flat();
+  const results = await Promise.allSettled(
+    Object.entries(byChain).map(([chain, vaults]) => processChain(chain, vaults))
+  );
+
+  return results
+    .filter((r) => r.status === 'fulfilled')
+    .flatMap((r) => r.value);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/adaptors/gami-labs/index.js` around lines 121 - 123, Promise.all
currently rejects when any processChain fails, dropping all pools; change the
aggregation to isolate per-chain failures by using Promise.allSettled (or
mapping each Object.entries(byChain).map to a try/catch wrapper) so individual
processChain errors are caught and logged but do not reject the whole batch;
collect only the fulfilled values into results (reference symbols: byChain,
processChain, results, Promise.all/Promise.allSettled) and ensure failures are
logged/filtered out before flattening the final pools array.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/adaptors/gami-labs/index.js`:
- Around line 47-51: The fetchJson helper uses global fetch and can reject the
whole run when one chain fails; replace its usage in the gami-labs price fetch
path so calls to the coins.llama.fi endpoint use the project's axios helper
instead: call utils.getData (or wrap it with utils.withRetry for transient
429/5xx retries) in place of fetchJson, update the code paths in
apy()/processChain() that request prices to await utils.getData(...) (or await
utils.withRetry(utils.getData, ...)(...)) and preserve the existing error
behavior from getData so a single-chain transient error is retried/handled
without aborting all Promise.all results.
- Around line 101-111: The adapter currently sets project: 'gami-labs' (which
doesn't match any protocol slug) and emits PPS-only pools without any apy
fields; update the returned pool object in src/adaptors/gami-labs/index.js (the
function that builds the pool return with keys pool, chain, project, symbol,
tvlUsd, pricePerShare, underlyingTokens, poolMeta, url) to (1) use the correct
protocol slug instead of the hard-coded 'gami-labs' (replace with the canonical
slug constant or value used by your registry/metadata so the "known protocol
slug" check passes) and (2) ensure PPS-only pools still provide at least one
finite APY by populating apy/apyBase/apyReward when pricePerShare exists (for
example set apyBase = 0 and apy = 0 if you cannot compute a yield, or compute an
APY from pricePerShare changes if historical data is available) so the adapter
satisfies src/adaptors/test.js and src/handlers/triggerAdaptor.js filters.

---

Nitpick comments:
In `@src/adaptors/gami-labs/index.js`:
- Around line 121-123: Promise.all currently rejects when any processChain
fails, dropping all pools; change the aggregation to isolate per-chain failures
by using Promise.allSettled (or mapping each Object.entries(byChain).map to a
try/catch wrapper) so individual processChain errors are caught and logged but
do not reject the whole batch; collect only the fulfilled values into results
(reference symbols: byChain, processChain, results,
Promise.all/Promise.allSettled) and ensure failures are logged/filtered out
before flattening the final pools array.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 020ae875-7ef8-4e8c-b351-f165af7bb5c9

📥 Commits

Reviewing files that changed from the base of the PR and between 94f9341 and 9624aa9.

📒 Files selected for processing (1)
  • src/adaptors/gami-labs/index.js

Comment on lines +47 to +51
async function fetchJson(url) {
const r = await fetch(url);
if (!r.ok) throw new Error(`HTTP ${r.status} for ${url}`);
return r.json();
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Node engine requirement
fd -d 2 '^package\.json$' --exec cat {} \; | jq -r '.engines // "no engines field"'

# Does the repo convention use utils.getData / axios for off-chain calls?
rg -nP "utils\.getData\s*\(" -g 'src/adaptors/**' | head -n 20

# Any existing adaptors relying on global fetch (to gauge precedent)?
rg -nP '(^|[^.\w])fetch\s*\(' -g 'src/adaptors/**' | head -n 20

# Confirm utils exposes getData
rg -nP '\bgetData\b' -g 'src/adaptors/utils.js' -C2

Repository: DefiLlama/yield-server

Length of output: 4188


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect gami-labs adaptor around the reported lines
fd -a '^src/adaptors/gami-labs/index\.js$' . | while read -r f; do
  echo "### $f"
  nl -ba "$f" | sed -n '35,160p'
done

# Inspect utils.getData implementation and any axios timeout/retry/non-2xx handling
fd -a '^src/adaptors/utils\.js$' . | while read -r f; do
  echo "### $f (getData)"
  nl -ba "$f" | sed -n '1,220p'
done

Repository: DefiLlama/yield-server

Length of output: 48


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== gami-labs/index.js =="
f="$(fd -a -t f 'gami-labs/index\.js$' src/adaptors . | head -n 1 || true)"
echo "Found: $f"
if [ -n "${f:-}" ]; then
  nl -ba "$f" | sed -n '1,220p'
fi

echo
echo "== src/adaptors/utils.js (getData) =="
u="$(fd -a -t f '^utils\.js$' src/adaptors . | head -n 1 || true)"
echo "Found: $u"
if [ -n "${u:-}" ]; then
  nl -ba "$u" | sed -n '70,170p'
fi

echo
echo "== Search gami-labs for fetchJson + processChain usage =="
if [ -n "${f:-}" ]; then
  rg -n "fetchJson|processChain" "$f" || true
fi

Repository: DefiLlama/yield-server

Length of output: 261


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check for src/adaptors/utils.js =="
if [ -f src/adaptors/utils.js ]; then
  echo "Found src/adaptors/utils.js"
  cat -n src/adaptors/utils.js | sed -n '80,170p'
else
  echo "src/adaptors/utils.js not found"
  fd -t f 'utils\.js$' src/adaptors --full-path | head -n 50
fi

echo
echo "== Locate gami-labs/index.js =="
fd -t f 'index\.js$' src/adaptors --full-path | rg -n 'gami[-_]?labs' || true
fd -t f 'gami[-_]?labs' src/adaptors --full-path | head -n 50 || true

Repository: DefiLlama/yield-server

Length of output: 3803


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== gami-labs/index.js (lines 1-220) =="
cat -n src/adaptors/gami-labs/index.js | sed -n '1,220p'

echo
echo "== gami-labs/index.js: fetchJson/processChain usages =="
rg -n "fetchJson|processChain|Promise\.all|allSettled|withRetry|utils\.getData" src/adaptors/gami-labs/index.js

echo
echo "== gami-labs/index.js: any direct fetch usage =="
rg -n "(^|[^.\w])fetch\s*\(" src/adaptors/gami-labs/index.js

Repository: DefiLlama/yield-server

Length of output: 7785


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== package.json engines (if any) =="
fd -t f 'package\.json$' . --full-path | while read -r p; do
  echo "-- $p"
  cat "$p" | rg -n '"engines"\s*:' -n || true
  # show engines block if present (first ~40 lines around it)
  if cat "$p" | rg -n '"engines"\s*:' >/dev/null; then
    line=$(cat "$p" | rg -n '"engines"\s*:' | head -n1 | cut -d: -f1)
    start=$((line-5)); end=$((line+25))
    cat -n "$p" | sed -n "${start},${end}p"
  fi
done

echo
echo "== Does code use utils.withRetry anywhere? =="
rg -n "utils\.withRetry\s*\(" -g 'src/adaptors/**' | head -n 50 || true

echo
echo "== Does any code call withRetry around utils.getData? =="
rg -n "withRetry\s*\(\s*\(\)\s*=>\s*utils\.getData|withRetry\s*\(\s*async\s*\(\)\s*=>\s*utils\.getData|getData\([^)]*\)\s*\)" -g 'src/adaptors/**' | head -n 50 || true

echo
echo "== Any custom timeout config for axios in utils? =="
rg -n "axios\.(create|defaults|interceptors).*timeout|timeout\s*:" src/adaptors/utils.js || true

echo
echo "== gami-labs/index.js uses withRetry or utils.getData? =="
rg -n "withRetry|getData" src/adaptors/gami-labs/index.js || true

Repository: DefiLlama/yield-server

Length of output: 7397


Replace native fetch with utils.getData (optionally wrapped in utils.withRetry) for gami-labs price fetching.

src/adaptors/gami-labs/index.js uses fetchJson() (global fetch, throws on !r.ok) to call https://coins.llama.fi/prices/current/...; because apy() runs processChain() across chains via Promise.all, a transient non-2xx/connection issue for one chain rejects the whole adaptor run and drops results for all pools. The repo’s utils.getData is axios-based (throws on non-2xx) and retry handling is available via utils.withRetry (429 + 5xx), so route this request through those helpers instead of raw fetch.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/adaptors/gami-labs/index.js` around lines 47 - 51, The fetchJson helper
uses global fetch and can reject the whole run when one chain fails; replace its
usage in the gami-labs price fetch path so calls to the coins.llama.fi endpoint
use the project's axios helper instead: call utils.getData (or wrap it with
utils.withRetry for transient 429/5xx retries) in place of fetchJson, update the
code paths in apy()/processChain() that request prices to await
utils.getData(...) (or await utils.withRetry(utils.getData, ...)(...)) and
preserve the existing error behavior from getData so a single-chain transient
error is retried/handled without aborting all Promise.all results.

Comment on lines +101 to +111
return {
pool: `${v.address.toLowerCase()}-${sdkChain}`,
chain: CHAIN_DISPLAY[sdkChain] || sdkChain,
project: 'gami-labs',
symbol: sym || v.name,
tvlUsd,
pricePerShare,
underlyingTokens: [asset.toLowerCase()],
poolMeta: v.name,
url: v.url,
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm the registered protocol slug for Gami Labs
curl -s https://api.llama.fi/protocols | jq -r '.[] | select(.name|test("gami";"i")) | "\(.name) -> \(.slug)"'

Repository: DefiLlama/yield-server

Length of output: 293


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check protocols list for slug gami-labs and name 'Gami Labs' ==="
curl -s https://api.llama.fi/protocols | jq -r '
  [
    (.[] | select(.slug=="gami-labs") | "\(.name) -> \(.slug)"),
    (.[] | select((.name|ascii_downcase)=="gami labs" ) | "\(.name) -> \(.slug)"),
    (.[] | select((.slug|ascii_downcase|test("gami-labs")) ) | "\(.name) -> \(.slug)"),
    (.[] | select((.name|ascii_downcase|test("gami labs")) ) | "\(.name) -> \(.slug)")
  ] | map(select(length>0)) | flatten | unique | .[]
' | head -n 50

echo
echo "=== Also dump any protocol slugs containing 'gami-labs' ==="
curl -s https://api.llama.fi/protocols | jq -r '.[] | select((.slug|ascii_downcase|test("gami-labs"))) | "\(.name) -> \(.slug)"' | head -n 50

echo
echo "=== Dump any protocol names containing 'Gami Labs' or 'gami labs' ==="
curl -s https://api.llama.fi/protocols | jq -r '.[] | select((.name|ascii_downcase|test("gami labs"))) | "\(.name) -> \(.slug)"' | head -n 50

Repository: DefiLlama/yield-server

Length of output: 267


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Inspect gami-labs adapter around lines ~80-140 ==="
# Try to locate file first
ls -la src/adaptors/gami-labs || true
sed -n '1,220p' src/adaptors/gami-labs/index.js | nl -ba | sed -n '70,160p'

echo
echo "=== Find how pricePerShare is used in this adapter ==="
rg -n "pricePerShare|apyBase|apyReward|apy\\b|project\\s*:" src/adaptors/gami-labs/index.js

echo
echo "=== Find sanity/schema checks mentioning pricePerShare in repo ==="
rg -n "pricePerShare|apyBase|apyReward|apy\\b" test src | head -n 200

Repository: DefiLlama/yield-server

Length of output: 360


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Run adapter test for gami-labs (best effort) ==="
npm -s run test --adapter=gami-labs

Repository: DefiLlama/yield-server

Length of output: 3521


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== protocols: exact slug 'gami-labs' existence (count) ==="
curl -s https://api.llama.fi/protocols | jq -r '
  (map(select(.slug=="gami-labs")) | length) as $n
  | "count=" + ($n|tostring)
'

echo
echo "=== protocols: any slug containing 'gami-labs' ==="
curl -s https://api.llama.fi/protocols | jq -r '
  .[]
  | select((.slug|ascii_downcase|test("gami-labs")))
  | "\(.name) -> \(.slug)"
' | head -n 50

echo
echo "=== protocols: any name containing 'gami labs' (exact words) or 'gami-labs' ==="
curl -s https://api.llama.fi/protocols | jq -r '
  .[]
  | select(
      ((.name|ascii_downcase|test("gami labs")) or (.name|ascii_downcase|test("gami-labs")))
    )
  | "\(.name) -> \(.slug)"
' | head -n 50

echo
echo "=== protocols: any slug with 'gami' (first 30) ==="
curl -s https://api.llama.fi/protocols | jq -r '
  .[]
  | select((.slug|ascii_downcase|test("gami")))
  | "\(.name) -> \(.slug)"
' | head -n 30

Repository: DefiLlama/yield-server

Length of output: 546


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/adaptors/gami-labs/index.js"
echo "=== file stats ==="
wc -l "$FILE"

echo
echo "=== project field(s) in adapter ==="
rg -n "project\\s*:" "$FILE" || true

echo
echo "=== pricePerShare / apy fields in adapter ==="
rg -n "pricePerShare|apyBase|apyReward|\\bapy\\b" "$FILE" || true

echo
echo "=== show around return block (approx lines 80-140) ==="
sed -n '70,160p' "$FILE" | cat -n

Repository: DefiLlama/yield-server

Length of output: 2765


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== repo: locate schema/sanity checks referencing pricePerShare ==="
rg -n "pricePerShare" test src | head -n 200

echo
echo "=== repo: locate required field checks for apy/pps ==="
rg -n "apyBase|apyReward|\\bapy\\b|sanity|schema" test src | head -n 200

Repository: DefiLlama/yield-server

Length of output: 49220


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed_show () {
  local f="$1"; local start="$2"; local end="$3";
  echo "---- $f:$start-$end ----"
  sed -n "${start},${end}p" "$f"
}

echo "=== inspect src/queries/yield.js around pricePerShare definition ==="
wc -l src/queries/yield.js
sed_show src/queries/yield.js 320 420

echo
echo "=== inspect src/api/controllers/yield.js around pricePerShare ==="
wc -l src/api/controllers/yield.js
sed_show src/api/controllers/yield.js 1 120
sed_show src/api/controllers/yield.js 120 220
sed_show src/api/controllers/yield.js 220 320

echo
echo "=== inspect src/handlers/triggerAdaptor.js around pricePerShare ==="
wc -l src/handlers/triggerAdaptor.js
sed_show src/handlers/triggerAdaptor.js 80 180
sed_show src/handlers/triggerAdaptor.js 260 360
sed_show src/handlers/triggerAdaptor.js 360 480

echo
echo "=== inspect src/adaptors/test.js around pricePerShare schema ==="
wc -l src/adaptors/test.js
rg -n "pricePerShare" src/adaptors/test.js | head -n 50
sed_show src/adaptors/test.js 1 120
sed_show src/adaptors/test.js 180 260

Repository: DefiLlama/yield-server

Length of output: 22531


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== inspect src/types/Pool.d.ts ==="
wc -l src/types/Pool.d.ts
sed -n '1,120p' src/types/Pool.d.ts

echo
echo "=== locate sanity/schema validator code for pools ==="
rg -n "sanity|schema" src | head -n 200

echo
echo "=== locate required/allowed fields in pool validation ==="
rg -n "apyBase|apyReward|apy\\b|pricePerShare" src | rg -n "required|validate|schema|sanity" | head -n 200

Repository: DefiLlama/yield-server

Length of output: 2441


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== repo root ==="
ls -la | head -n 80

echo
echo "=== directories ==="
ls -d */ | head -n 200

echo
echo "=== Find how 'project' is used/validated ==="
rg -n "project" src/api src/queries src/handlers src/types | head -n 200

echo
echo "=== Find protocol slug linking logic (project/slug) ==="
rg -n "slug.*project|project.*slug|protocol.*project|project.*protocol" src | head -n 200

Repository: DefiLlama/yield-server

Length of output: 14446


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed_show () {
  local f="$1"; local start="$2"; local end="$3";
  echo "---- $f:$start-$end ----"
  sed -n "${start},${end}p" "$f"
}

echo "=== inspect src/queries/yield.js around pricePerShare definition ==="
wc -l src/queries/yield.js
sed_show src/queries/yield.js 320 420

echo
echo "=== inspect src/api/controllers/yield.js around pricePerShare ==="
wc -l src/api/controllers/yield.js
sed_show src/api/controllers/yield.js 1 130
sed_show src/api/controllers/yield.js 130 240
sed_show src/api/controllers/yield.js 240 340

echo
echo "=== inspect src/handlers/triggerAdaptor.js around pricePerShare ==="
wc -l src/handlers/triggerAdaptor.js
sed_show src/handlers/triggerAdaptor.js 80 190
sed_show src/handlers/triggerAdaptor.js 250 360
sed_show src/handlers/triggerAdaptor.js 360 480

echo
echo "=== inspect src/adaptors/test.js around pricePerShare schema ==="
wc -l src/adaptors/test.js
rg -n "pricePerShare" src/adaptors/test.js | head -n 30
sed_show src/adaptors/test.js 1 140
sed_show src/adaptors/test.js 160 260
sed_show src/adaptors/test.js 260 340

Repository: DefiLlama/yield-server

Length of output: 24740


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== inspect src/types/Pool.d.ts ==="
wc -l src/types/Pool.d.ts
sed -n '1,140p' src/types/Pool.d.ts

echo
echo "=== locate pool validation/sanity logic ==="
rg -n "sanity|schema" src | head -n 200
echo
echo "=== locate validators mentioning apy or pricePerShare ==="
rg -n "validate|sanity|schema" src | rg -n "apyBase|apyReward|pricePerShare|apy\\b" | head -n 200

Repository: DefiLlama/yield-server

Length of output: 2328


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== repo root ==="
ls -la | head -n 80

echo
echo "=== directories ==="
ls -d */ | head -n 200

echo
echo "=== Find how 'project' is used/validated ==="
rg -n "project" src/api src/queries src/handlers src/types | head -n 200

echo
echo "=== Find protocol slug linking logic (project/slug) ==="
rg -n "slug.*project|project.*slug|protocol.*project|project.*protocol" src | head -n 200

Repository: DefiLlama/yield-server

Length of output: 14446


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed_show () {
  local f="$1"; local start="$2"; local end="$3";
  echo "---- $f:$start-$end ----"
  sed -n "${start},${end}p" "$f"
}

echo "=== inspect src/queries/yield.js around pricePerShare definition ==="
wc -l src/queries/yield.js
sed_show src/queries/yield.js 320 420

echo
echo "=== inspect src/api/controllers/yield.js around pricePerShare ==="
wc -l src/api/controllers/yield.js
sed_show src/api/controllers/yield.js 1 130
sed_show src/api/controllers/yield.js 130 240
sed_show src/api/controllers/yield.js 240 340

echo
echo "=== inspect src/handlers/triggerAdaptor.js around pricePerShare ==="
wc -l src/handlers/triggerAdaptor.js
wc -l src/handlers/triggerAdaptor.js
sed_show src/handlers/triggerAdaptor.js 80 190
sed_show src/handlers/triggerAdaptor.js 250 360
sed_show src/handlers/triggerAdaptor.js 360 480

echo
echo "=== inspect src/adaptors/test.js around pricePerShare schema ==="
wc -l src/adaptors/test.js
rg -n "pricePerShare" src/adaptors/test.js | head -n 30
sed_show src/adaptors/test.js 1 140
sed_show src/adaptors/test.js 160 260
sed_show src/adaptors/test.js 260 340

Repository: DefiLlama/yield-server

Length of output: 24775


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== inspect src/types/Pool.d.ts ==="
wc -l src/types/Pool.d.ts
sed -n '1,140p' src/types/Pool.d.ts

echo
echo "=== locate pool validation/sanity logic ==="
rg -n "sanity|schema" src | head -n 200
echo
echo "=== locate validators mentioning apy or pricePerShare ==="
rg -n "validate|sanity|schema" src | rg -n "apyBase|apyReward|pricePerShare|apy\\b" | head -n 200

Repository: DefiLlama/yield-server

Length of output: 2328


Fix project slug + ensure PPS-only pools provide apy* (tests/pipeline drop otherwise)

  • src/adaptors/gami-labs/index.js sets project: 'gami-labs', but https://api.llama.fi/protocols contains no protocol with slug == "gami-labs" (count=0) — so adapter test’s “known protocol slug” check should fail.
  • The repo’s sanity checks don’t accept PPS-only pools: src/adaptors/test.js requires at least one finite value among apy/apyBase/apyReward, and src/handlers/triggerAdaptor.js filters out pools where all three are null. So PPS-only pools must still emit apy* (or the pipeline/tests need updating to support PPS-only).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/adaptors/gami-labs/index.js` around lines 101 - 111, The adapter
currently sets project: 'gami-labs' (which doesn't match any protocol slug) and
emits PPS-only pools without any apy fields; update the returned pool object in
src/adaptors/gami-labs/index.js (the function that builds the pool return with
keys pool, chain, project, symbol, tvlUsd, pricePerShare, underlyingTokens,
poolMeta, url) to (1) use the correct protocol slug instead of the hard-coded
'gami-labs' (replace with the canonical slug constant or value used by your
registry/metadata so the "known protocol slug" check passes) and (2) ensure
PPS-only pools still provide at least one finite APY by populating
apy/apyBase/apyReward when pricePerShare exists (for example set apyBase = 0 and
apy = 0 if you cannot compute a yield, or compute an APY from pricePerShare
changes if historical data is available) so the adapter satisfies
src/adaptors/test.js and src/handlers/triggerAdaptor.js filters.

@github-actions
Copy link
Copy Markdown

Error while running gami-labs adapter:

Test Suites: 1 failed, 1 total
Tests: 1 failed, 123 passed, 124 total
Snapshots: 0 total
Time: 0.319 s
Ran all test suites.

Nb of pools: 15
 

Sample pools:
┌─────────┬───────────────────────────────────────────────────────┬─────────────┬─────────────┬─────────────┬────────────────────┬─────────┬───────────────┬──────────────────────────────────────────────────┬─────────────────────────────┬───────────────────────────────────────────────────────────────────────────────┐
│ (index) │ pool                                                  │ chain       │ project     │ symbol      │ tvlUsd             │ apyBase │ pricePerShare │ underlyingTokens                                 │ poolMeta                    │ url                                                                           │
├─────────┼───────────────────────────────────────────────────────┼─────────────┼─────────────┼─────────────┼────────────────────┼─────────┼───────────────┼──────────────────────────────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ 0       │ '0x776f95321a0285f8bcde149e3264d16dc08da69a-base'     │ 'Base'      │ 'gami-labs' │ 'gamisUSDC' │ 4530575.619652607  │ 0       │ 1.024141      │ [ '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' ] │ 'Gami Spectra USDC'         │ 'https://gamilabs.io/vaults/8453/0x5e93e1193a5e297cba0856e9b3f22b6e05429b9a'  │
│ 1       │ '0x6420a613e936602ca3f1ad5680b3f4d47d473bf1-flare'    │ 'Flare'     │ 'gami-labs' │ 'gamisXRP'  │ 4224371.187218211  │ 0       │ 1.000363      │ [ '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │ 'Flare XRP Yield Prime'     │ 'https://gamilabs.io/vaults/14/0x0c4f32c53d4b91a019c7c9d8da14af140295eef6'    │
│ 2       │ '0x2a676c2744421b4fae65ce86b47adacb620047d4-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'ghemiBTC'  │ 3790403.911844111  │ 0       │ 1.0111261     │ [ '0x06ea695b91700071b161a434fed42d1dcbad9f00' ] │ 'Gami hemiBTC'              │ 'https://gamilabs.io/vaults/1/0x2a676c2744421b4fae65ce86b47adacb620047d4'     │
│ 3       │ '0x57e6824a8b15b709cefb4ccef644ba1349057e77-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'xBTCY'     │ 3702953.2263282435 │ 0       │ 1             │ [ '0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf' ] │ 'xBTCY'                     │ 'https://gamilabs.io/vaults/1/0x57e6824a8b15b709cefb4ccef644ba1349057e77'     │
│ 4       │ '0xdae854d0896ad2fee335689a3f7b4a95fd1a3e46-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'gamiusdc'  │ 2711839.6426244373 │ 0       │ 1.060237      │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Gami USDC'                 │ 'https://gamilabs.io/vaults/1/0xdae854d0896ad2fee335689a3f7b4a95fd1a3e46'     │
│ 5       │ '0x1f0570a081fee0e4df6eac470f9d2d53cdeda1c5-avax'     │ 'Avalanche' │ 'gami-labs' │ 'USDC'      │ 1229026.6751955668 │ 0       │ 0.000001      │ [ '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e' ] │ 'Gami Silo USDC'            │ 'https://gamilabs.io/vaults/43114/0x1F0570a081FeE0e4dF6eAC470f9d2D53CDEDa1c5' │
│ 6       │ '0xb3a2bcb30c1460d88db18b42a29fae2399952874-avax'     │ 'Avalanche' │ 'gami-labs' │ 'agUSDC'    │ 1018913.262991238  │ 0       │ 1.015863      │ [ '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e' ] │ 'USDC Avalanche Core'       │ 'https://gamilabs.io/vaults/43114/0xb3a2bcb30c1460d88db18b42a29fae2399952874' │
│ 7       │ '0xfab0f56c28e3f874b15922b213e696f37b670916-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'gamicUSPC' │ 995202.0120096215  │ 0       │ 1.019789      │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Coinshift USPC Prime'      │ 'https://gamilabs.io/vaults/1/0xfab0f56c28e3f874b15922b213e696f37b670916'     │
│ 8       │ '0x414070fb9e64fd69160d75da57e75ba11f9f605a-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'gamiWBTC'  │ 607146.9684733747  │ 0       │ 1.02597055    │ [ '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599' ] │ 'Gami WBTC'                 │ 'https://gamilabs.io/vaults/1/0x414070fb9e64fd69160d75da57e75ba11f9f605a'     │
│ 9       │ '0x09252d2c4afca9b1479efdd39faa53de9ff23114-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'gamilUSPC' │ 501322.38301505696 │ 0       │ 1.002458      │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Coinshift USPC High Yield' │ 'https://gamilabs.io/vaults/1/0x09252d2c4afca9b1479efdd39faa53de9ff23114'     │
└─────────┴───────────────────────────────────────────────────────┴─────────────┴─────────────┴─────────────┴────────────────────┴─────────┴───────────────┴──────────────────────────────────────────────────┴─────────────────────────────┴───────────────────────────────────────────────────────────────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

@github-actions
Copy link
Copy Markdown

The gami-labs adapter exports pools:

Test Suites: 1 passed, 1 total
Tests: 124 passed, 124 total
Snapshots: 0 total
Time: 0.268 s
Ran all test suites.

Nb of pools: 15
 

Sample pools:
┌─────────┬───────────────────────────────────────────────────────┬─────────────┬─────────────┬─────────────┬────────────────────┬─────────┬───────────────┬──────────────────────────────────────────────────┬─────────────────────────────┬───────────────────────────────────────────────────────────────────────────────┐
│ (index) │ pool                                                  │ chain       │ project     │ symbol      │ tvlUsd             │ apyBase │ pricePerShare │ underlyingTokens                                 │ poolMeta                    │ url                                                                           │
├─────────┼───────────────────────────────────────────────────────┼─────────────┼─────────────┼─────────────┼────────────────────┼─────────┼───────────────┼──────────────────────────────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ 0       │ '0x776f95321a0285f8bcde149e3264d16dc08da69a-base'     │ 'Base'      │ 'gami-labs' │ 'gamisUSDC' │ 4531170.641106398  │ 0       │ 1.024141      │ [ '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' ] │ 'Gami Spectra USDC'         │ 'https://gamilabs.io/vaults/8453/0x5e93e1193a5e297cba0856e9b3f22b6e05429b9a'  │
│ 1       │ '0x6420a613e936602ca3f1ad5680b3f4d47d473bf1-flare'    │ 'Flare'     │ 'gami-labs' │ 'gamisXRP'  │ 4271354.250463691  │ 0       │ 1.000363      │ [ '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │ 'Flare XRP Yield Prime'     │ 'https://gamilabs.io/vaults/14/0x0c4f32c53d4b91a019c7c9d8da14af140295eef6'    │
│ 2       │ '0x2a676c2744421b4fae65ce86b47adacb620047d4-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'ghemiBTC'  │ 3767136.974111208  │ 0       │ 1.0111261     │ [ '0x06ea695b91700071b161a434fed42d1dcbad9f00' ] │ 'Gami hemiBTC'              │ 'https://gamilabs.io/vaults/1/0x2a676c2744421b4fae65ce86b47adacb620047d4'     │
│ 3       │ '0x57e6824a8b15b709cefb4ccef644ba1349057e77-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'xBTCY'     │ 3679718.7276043687 │ 0       │ 1             │ [ '0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf' ] │ 'xBTCY'                     │ 'https://gamilabs.io/vaults/1/0x57e6824a8b15b709cefb4ccef644ba1349057e77'     │
│ 4       │ '0xdae854d0896ad2fee335689a3f7b4a95fd1a3e46-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'gamiusdc'  │ 2713416.8191664605 │ 0       │ 1.06055       │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Gami USDC'                 │ 'https://gamilabs.io/vaults/1/0xdae854d0896ad2fee335689a3f7b4a95fd1a3e46'     │
│ 5       │ '0x1f0570a081fee0e4df6eac470f9d2d53cdeda1c5-avax'     │ 'Avalanche' │ 'gami-labs' │ 'USDC'      │ 1228705.5013038046 │ 0       │ 0.000001      │ [ '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e' ] │ 'Gami Silo USDC'            │ 'https://gamilabs.io/vaults/43114/0x1F0570a081FeE0e4dF6eAC470f9d2D53CDEDa1c5' │
│ 6       │ '0xb3a2bcb30c1460d88db18b42a29fae2399952874-avax'     │ 'Avalanche' │ 'gami-labs' │ 'agUSDC'    │ 1019601.1522993292 │ 0       │ 1.016365      │ [ '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e' ] │ 'USDC Avalanche Core'       │ 'https://gamilabs.io/vaults/43114/0xb3a2bcb30c1460d88db18b42a29fae2399952874' │
│ 7       │ '0xfab0f56c28e3f874b15922b213e696f37b670916-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'gamicUSPC' │ 995259.7585699704  │ 0       │ 1.019789      │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Coinshift USPC Prime'      │ 'https://gamilabs.io/vaults/1/0xfab0f56c28e3f874b15922b213e696f37b670916'     │
│ 8       │ '0x414070fb9e64fd69160d75da57e75ba11f9f605a-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'gamiWBTC'  │ 602266.5873597132  │ 0       │ 1.02597055    │ [ '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599' ] │ 'Gami WBTC'                 │ 'https://gamilabs.io/vaults/1/0x414070fb9e64fd69160d75da57e75ba11f9f605a'     │
│ 9       │ '0x09252d2c4afca9b1479efdd39faa53de9ff23114-ethereum' │ 'Ethereum'  │ 'gami-labs' │ 'gamilUSPC' │ 501351.47222799633 │ 0       │ 1.002458      │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Coinshift USPC High Yield' │ 'https://gamilabs.io/vaults/1/0x09252d2c4afca9b1479efdd39faa53de9ff23114'     │
└─────────┴───────────────────────────────────────────────────────┴─────────────┴─────────────┴─────────────┴────────────────────┴─────────┴───────────────┴──────────────────────────────────────────────────┴─────────────────────────────┴───────────────────────────────────────────────────────────────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant