From 0caf35ffe28b280a44067d54df6b89899c9ac2e3 Mon Sep 17 00:00:00 2001 From: Bouneb Rayan Date: Sun, 19 Jan 2025 00:48:31 +0100 Subject: [PATCH 1/5] Added spooky-lp-sonic strategy and updated index.ts --- src/strategies/index.ts | 2 + src/strategies/spooky-lp-sonic/README.md | 13 +++ src/strategies/spooky-lp-sonic/examples.json | 17 +++ src/strategies/spooky-lp-sonic/index.ts | 111 +++++++++++++++++++ 4 files changed, 143 insertions(+) create mode 100644 src/strategies/spooky-lp-sonic/README.md create mode 100644 src/strategies/spooky-lp-sonic/examples.json create mode 100644 src/strategies/spooky-lp-sonic/index.ts diff --git a/src/strategies/index.ts b/src/strategies/index.ts index 100a05eb8..7a67268a5 100644 --- a/src/strategies/index.ts +++ b/src/strategies/index.ts @@ -470,8 +470,10 @@ import * as morphoDelegation from './morpho-delegation'; import * as lizcoinStrategy2024 from './lizcoin-strategy-2024'; import * as realt from './realt'; import * as superfluidVesting from './superfluid-vesting'; +import * as spookyLpSonic from './spooky-lp-sonic'; const strategies = { + 'spooky-lp-sonic': spookyLpSonic, 'delegatexyz-erc721-balance-of': delegatexyzErc721BalanceOf, 'giveth-balances-supply-weighted': givethBalancesSupplyWeighted, 'giveth-gnosis-balance-supply-weighted-v3': diff --git a/src/strategies/spooky-lp-sonic/README.md b/src/strategies/spooky-lp-sonic/README.md new file mode 100644 index 000000000..4571feba1 --- /dev/null +++ b/src/strategies/spooky-lp-sonic/README.md @@ -0,0 +1,13 @@ +# LP Liquidity Position for $BOO Pools [Sonic] +This strategy calculates the liquidity position of users in pools where $BOO is one of the tokens. It utilizes data from a subgraph to compute the net liquidity by analyzing mint and burn events. + +## Overview +The strategy queries the following pools: + +Pool 1: 0x686d873a9e0696afaca0bc163dcc95b577d9e3e8 wS/BOO +Pool 2: 0xf4dcfaa2711908a8c61d9516d84b24ffdae241db WETH/BOO +Pool 3: 0xb7228a39cdd2c734064fc95c54e75910ff06eed6 USDC.E/BOO +Pool 4: 0x84d4716c1cf4d7b1b1c247ad69b62fa72ccc46d7 wS/BOO +Pool 5: 0xaa4ee51f55f9baa7cf180fbaf2688cc35fdc8012 BOO/TONS + +The strategy uses a subgraph to fetch mint and burn events, calculates the net liquidity position, and assigns scores to the provided addresses based on their activity. \ No newline at end of file diff --git a/src/strategies/spooky-lp-sonic/examples.json b/src/strategies/spooky-lp-sonic/examples.json new file mode 100644 index 000000000..c93e88c72 --- /dev/null +++ b/src/strategies/spooky-lp-sonic/examples.json @@ -0,0 +1,17 @@ +[ + { + "name": "Example query", + "strategy": { + "name": "spooky-lp-sonic" + }, + "network": "1", + "addresses": [ + "0xf83e546bd2959c22f1715ecaffc03d39b8d0fa96", + "0x02fa5640f5D948f14C9195fB2873D832A49f0A5f", + "0xFE2fb8587760c8d5960CB7A5BA2f2299EdF10506", + "0x593B0c00078A741eB440c7B9Dde999bdD40Aa1F9", + "0x159b567635aea41170aafaf1f832185344c56fba" + ], + "snapshot": 11437846 + } +] diff --git a/src/strategies/spooky-lp-sonic/index.ts b/src/strategies/spooky-lp-sonic/index.ts new file mode 100644 index 000000000..1cabe679b --- /dev/null +++ b/src/strategies/spooky-lp-sonic/index.ts @@ -0,0 +1,111 @@ +import { subgraphRequest } from '../../utils'; +import { getAddress } from '@ethersproject/address'; + +const MY_SUBGRAPH_URL ={ + '1': 'https://api.0xgraph.xyz/api/public/28820bd2-ad8b-4d40-a142-ce8d7c786f66/subgraphs/spookyswap/v3/v0.0.1/gn' +}; + +export const author = 'function03-labs'; +export const version = '0.1.0'; + + +async function subgraphRequestWithPagination(subgraphURL, addresses, poolId, snapshot) { + const chunkSize = 1000; + const chunks: string[][] = []; + for (let i = 0; i < addresses.length; i += chunkSize) { + chunks.push(addresses.slice(i, i + chunkSize)); + } + + const results: { mints: { origin: string; timestamp: string; amount: string; pool: { id: string } }[], burns: { origin: string; timestamp: string; amount: string; pool: { id: string } }[] } = { mints: [], burns: [] }; + for (const chunk of chunks) { + const params = { + mints: { + __args: { + where: { + pool_: { id: poolId }, + origin_in: chunk.map((address) => address.toLowerCase()) + }, + first: 1000, + }, + origin: true, + timestamp: true, + amount: true, + pool: { id: true } + }, + burns: { + __args: { + where: { + pool_: { id: poolId }, + origin_in: chunk.map((address) => address.toLowerCase()) + }, + first: 1000 + }, + origin: true, + timestamp: true, + amount: true, + pool: { id: true } + } + }; + + if (snapshot !== 'latest') { + // Add block parameter + // @ts-ignore + params.mints.__args.where.transaction_ = { blockNumber_lte: snapshot }; + // @ts-ignore + params.burns.__args.where.transaction_ = { blockNumber_lte: snapshot }; + } + //console.log(params); + try { + const result = await subgraphRequest(subgraphURL, params); + if (result?.mints) results.mints.push(...result.mints); + if (result?.burns) results.burns.push(...result.burns); + } catch (error) { + //console.error(`Error querying pool ${poolId}:`, error); + } + } + + return results; +} + +export async function strategy( + space, + network, + provider, + addresses, + options, + snapshot + ) { + const poolIds = [ + "0x686d873a9e0696afaca0bc163dcc95b577d9e3e8", + "0xf4dcfaa2711908a8c61d9516d84b24ffdae241db", + "0xb7228a39cdd2c734064fc95c54e75910ff06eed6", + "0x84d4716c1cf4d7b1b1c247ad69b62fa72ccc46d7", + "0xaa4ee51f55f9baa7cf180fbaf2688cc35fdc8012", + ]; + + const subgraphURL = MY_SUBGRAPH_URL[network]; + const score = {}; + addresses.forEach((address) => { + score[getAddress(address)] = 0; + }); + + for (const poolId of poolIds) { + const result = await subgraphRequestWithPagination(subgraphURL, addresses, poolId, snapshot); + if (result && (result.mints || result.burns)) { + const mints = result.mints; + const burns = result.burns; + mints.forEach((mint) => { + const userAddress = getAddress(mint.origin); + const amount = parseFloat(mint.amount); + score[userAddress] += amount; + }); + burns.forEach((burn) => { + const userAddress = getAddress(burn.origin); + const amount = parseFloat(burn.amount); + score[userAddress] -= amount; + }); + } + } + return score || {}; +} + From b2a14706ee09573c15d69e5917ac3c87fc90adb2 Mon Sep 17 00:00:00 2001 From: Bouneb Rayan Date: Thu, 23 Jan 2025 01:43:54 +0100 Subject: [PATCH 2/5] removed pagination for request limit --- src/strategies/spooky-lp-sonic/index.ts | 112 ++++++++++-------------- 1 file changed, 47 insertions(+), 65 deletions(-) diff --git a/src/strategies/spooky-lp-sonic/index.ts b/src/strategies/spooky-lp-sonic/index.ts index 1cabe679b..029b84cef 100644 --- a/src/strategies/spooky-lp-sonic/index.ts +++ b/src/strategies/spooky-lp-sonic/index.ts @@ -1,31 +1,43 @@ import { subgraphRequest } from '../../utils'; import { getAddress } from '@ethersproject/address'; -const MY_SUBGRAPH_URL ={ +const MY_SUBGRAPH_URL = { '1': 'https://api.0xgraph.xyz/api/public/28820bd2-ad8b-4d40-a142-ce8d7c786f66/subgraphs/spookyswap/v3/v0.0.1/gn' }; export const author = 'function03-labs'; export const version = '0.1.0'; +export async function strategy( + space, + network, + provider, + addresses, + options, + snapshot +) { + const poolIds = [ + "0x686d873a9e0696afaca0bc163dcc95b577d9e3e8", + "0xf4dcfaa2711908a8c61d9516d84b24ffdae241db", + "0xb7228a39cdd2c734064fc95c54e75910ff06eed6", + "0x84d4716c1cf4d7b1b1c247ad69b62fa72ccc46d7", + "0xaa4ee51f55f9baa7cf180fbaf2688cc35fdc8012", + ]; -async function subgraphRequestWithPagination(subgraphURL, addresses, poolId, snapshot) { - const chunkSize = 1000; - const chunks: string[][] = []; - for (let i = 0; i < addresses.length; i += chunkSize) { - chunks.push(addresses.slice(i, i + chunkSize)); - } + const subgraphURL = MY_SUBGRAPH_URL[network]; + const score = {}; + addresses.forEach((address) => { + score[getAddress(address)] = 0; + }); - const results: { mints: { origin: string; timestamp: string; amount: string; pool: { id: string } }[], burns: { origin: string; timestamp: string; amount: string; pool: { id: string } }[] } = { mints: [], burns: [] }; - for (const chunk of chunks) { + for (const poolId of poolIds) { const params = { mints: { __args: { where: { pool_: { id: poolId }, - origin_in: chunk.map((address) => address.toLowerCase()) - }, - first: 1000, + origin_in: addresses.map((address) => address.toLowerCase()) + } }, origin: true, timestamp: true, @@ -36,9 +48,8 @@ async function subgraphRequestWithPagination(subgraphURL, addresses, poolId, sna __args: { where: { pool_: { id: poolId }, - origin_in: chunk.map((address) => address.toLowerCase()) - }, - first: 1000 + origin_in: addresses.map((address) => address.toLowerCase()) + } }, origin: true, timestamp: true, @@ -48,64 +59,35 @@ async function subgraphRequestWithPagination(subgraphURL, addresses, poolId, sna }; if (snapshot !== 'latest') { - // Add block parameter // @ts-ignore - params.mints.__args.where.transaction_ = { blockNumber_lte: snapshot }; + params.mints.__args.where.transaction_ = { blockNumber_lte: snapshot }; // @ts-ignore - params.burns.__args.where.transaction_ = { blockNumber_lte: snapshot }; + params.burns.__args.where.transaction_ = { blockNumber_lte: snapshot }; } - //console.log(params); + try { const result = await subgraphRequest(subgraphURL, params); - if (result?.mints) results.mints.push(...result.mints); - if (result?.burns) results.burns.push(...result.burns); - } catch (error) { - //console.error(`Error querying pool ${poolId}:`, error); - } - } - - return results; -} - -export async function strategy( - space, - network, - provider, - addresses, - options, - snapshot - ) { - const poolIds = [ - "0x686d873a9e0696afaca0bc163dcc95b577d9e3e8", - "0xf4dcfaa2711908a8c61d9516d84b24ffdae241db", - "0xb7228a39cdd2c734064fc95c54e75910ff06eed6", - "0x84d4716c1cf4d7b1b1c247ad69b62fa72ccc46d7", - "0xaa4ee51f55f9baa7cf180fbaf2688cc35fdc8012", - ]; + if (result && (result.mints || result.burns)) { + const mints = result.mints; + const burns = result.burns; - const subgraphURL = MY_SUBGRAPH_URL[network]; - const score = {}; - addresses.forEach((address) => { - score[getAddress(address)] = 0; - }); + mints.forEach((mint) => { + const userAddress = getAddress(mint.origin); + const amount = parseFloat(mint.amount); + score[userAddress] += amount; + }); - for (const poolId of poolIds) { - const result = await subgraphRequestWithPagination(subgraphURL, addresses, poolId, snapshot); - if (result && (result.mints || result.burns)) { - const mints = result.mints; - const burns = result.burns; - mints.forEach((mint) => { - const userAddress = getAddress(mint.origin); - const amount = parseFloat(mint.amount); - score[userAddress] += amount; - }); - burns.forEach((burn) => { - const userAddress = getAddress(burn.origin); - const amount = parseFloat(burn.amount); - score[userAddress] -= amount; - }); + burns.forEach((burn) => { + const userAddress = getAddress(burn.origin); + const amount = parseFloat(burn.amount); + score[userAddress] -= amount; + }); + } + } catch (error) { + // console.error(`Error querying pool ${poolId}:`, error); + continue; } } + return score || {}; } - From 3d19653523e9f7aa89a036020e89d397b6e70eb2 Mon Sep 17 00:00:00 2001 From: Aiden <30964272+0xaaiden@users.noreply.github.com> Date: Thu, 23 Jan 2025 09:25:11 -0500 Subject: [PATCH 3/5] Update src/strategies/spooky-lp-sonic/index.ts Co-authored-by: Chaitanya --- src/strategies/spooky-lp-sonic/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategies/spooky-lp-sonic/index.ts b/src/strategies/spooky-lp-sonic/index.ts index 029b84cef..bac18f48e 100644 --- a/src/strategies/spooky-lp-sonic/index.ts +++ b/src/strategies/spooky-lp-sonic/index.ts @@ -5,7 +5,7 @@ const MY_SUBGRAPH_URL = { '1': 'https://api.0xgraph.xyz/api/public/28820bd2-ad8b-4d40-a142-ce8d7c786f66/subgraphs/spookyswap/v3/v0.0.1/gn' }; -export const author = 'function03-labs'; +export const author = '0xaaiden'; export const version = '0.1.0'; export async function strategy( From 963591a348484e915afa623fe1ee4f3951929072 Mon Sep 17 00:00:00 2001 From: Aiden <30964272+0xaaiden@users.noreply.github.com> Date: Thu, 23 Jan 2025 09:44:53 -0500 Subject: [PATCH 4/5] Refactor error handling in `src/strategies/spooky-lp-sonic/index.ts` * Remove try-catch block around subgraphRequest --- src/strategies/spooky-lp-sonic/index.ts | 33 +++++++++++-------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/src/strategies/spooky-lp-sonic/index.ts b/src/strategies/spooky-lp-sonic/index.ts index bac18f48e..ea9477e6f 100644 --- a/src/strategies/spooky-lp-sonic/index.ts +++ b/src/strategies/spooky-lp-sonic/index.ts @@ -65,27 +65,22 @@ export async function strategy( params.burns.__args.where.transaction_ = { blockNumber_lte: snapshot }; } - try { - const result = await subgraphRequest(subgraphURL, params); - if (result && (result.mints || result.burns)) { - const mints = result.mints; - const burns = result.burns; + const result = await subgraphRequest(subgraphURL, params); + if (result && (result.mints || result.burns)) { + const mints = result.mints; + const burns = result.burns; - mints.forEach((mint) => { - const userAddress = getAddress(mint.origin); - const amount = parseFloat(mint.amount); - score[userAddress] += amount; - }); + mints.forEach((mint) => { + const userAddress = getAddress(mint.origin); + const amount = parseFloat(mint.amount); + score[userAddress] += amount; + }); - burns.forEach((burn) => { - const userAddress = getAddress(burn.origin); - const amount = parseFloat(burn.amount); - score[userAddress] -= amount; - }); - } - } catch (error) { - // console.error(`Error querying pool ${poolId}:`, error); - continue; + burns.forEach((burn) => { + const userAddress = getAddress(burn.origin); + const amount = parseFloat(burn.amount); + score[userAddress] -= amount; + }); } } From 2644d025fe9809aef765ce85e54a4959444f7715 Mon Sep 17 00:00:00 2001 From: Chaitanya Date: Thu, 23 Jan 2025 20:39:24 +0530 Subject: [PATCH 5/5] Update src/strategies/index.ts --- src/strategies/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategies/index.ts b/src/strategies/index.ts index 7ab0e8756..12ba9d0c1 100644 --- a/src/strategies/index.ts +++ b/src/strategies/index.ts @@ -470,7 +470,7 @@ import * as naymsStaking from './nayms-staking'; import * as morphoDelegation from './morpho-delegation'; import * as lizcoinStrategy2024 from './lizcoin-strategy-2024'; import * as realt from './realt'; -import * as superfluidVesting from './superfluid-vesting +import * as superfluidVesting from './superfluid-vesting'; import * as spookyLpSonic from './spooky-lp-sonic'; import * as synapse from './synapse';