Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MMI-5405-investigate-and-solve-for-missing-product-on-stargate-to-ensure-we-have-full-coverage #304

Open
wants to merge 22 commits into
base: main
Choose a base branch
from

Conversation

bergarces
Copy link
Collaborator

@bergarces bergarces commented Aug 28, 2024

  • Added missing chains and metadata for Stargate V1 LP pools.
  • Added support for LP token staking for V1 and V2

@bergarces bergarces force-pushed the MMI-5405-investigate-and-solve-for-missing-product-on-stargate-to-ensure-we-have-full-coverage branch from a1b150c to 00f9a5f Compare August 29, 2024 21:20
@@ -33,6 +33,7 @@ export const Protocol = {
SparkV1: 'spark-v1',
StakeWise: 'stakewise',
Stargate: 'stargate',
StargateV2: 'stargate-v2',
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do we want stargate-v2 or do we want to group the new products inside stargate?

If we want to align our protocol ids with other providers, I don't think they have a stargate-v2.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I dont know what debank have....lets wait for the ticket

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

From their UI, it looks like everything is Stargate. Whether the API is the same or not, we don't know yet.

I've taken the safe approach and all of them are under Stargate now.

@bergarces bergarces marked this pull request as ready for review September 2, 2024 16:05
poolUsdcAddress?: string
poolUsdtAddress?: string
poolMetisAddress?: string
poolMethAddress?: string
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

There's no event or any contract I could find where these contract addresses live. They've been fetched from their docs.

https://stargateprotocol.gitbook.io/stargate/v/v2-developer-docs/technical-reference/mainnet-contracts

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This started crashing my local build due to the json file not matching with the class name.

Copy link
Collaborator

Choose a reason for hiding this comment

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

oh ok, not sure what happened there they must have change the name...good spot

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It was driving my nuts that every time we did something like v2 it will be converted to v-2, so I amended the implementation.

Copy link
Collaborator

Choose a reason for hiding this comment

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

yes nice improvement :)

Copy link

sonarcloud bot commented Sep 5, 2024

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 30%)
26.8% Duplication on New Code (required ≤ 7%)

See analysis details on SonarCloud

Comment on lines +142 to +147
if (
protocolTokenAddresses &&
!protocolTokenAddresses.includes(protocolToken.address)
) {
return undefined
}
Copy link
Collaborator

@jpsains jpsains Sep 6, 2024

Choose a reason for hiding this comment

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

Do you see a future where we can drop having to do this filter inside the adapter? Wondering if the filtering could be done outside....

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

To be honest, I can't.

If we do it outside that means the return function will be something like Promise<ReturnType | undefined>, which doesn't make a lot of sense.

Moreover, we use that pattern pretty often internally as well, which means that if we don't get rid of it quickly and we chain the result to another array method, the first thing we'll have to do is check if it's undefined.

It's unfortunate that JS doesn't come with an array method that does that automatically.

Comment on lines +272 to +297
return events.map((event) => {
const { amount } = event.args!

return {
protocolToken: {
address: protocolToken.address,
name: protocolToken.name,
symbol: protocolToken.symbol,
decimals: protocolToken.decimals,
},
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
tokens: [
{
address: protocolToken.address,
name: protocolToken.name,
symbol: protocolToken.symbol,
decimals: protocolToken.decimals,
type: TokenType.Underlying,
blockNumber: event.blockNumber,
balanceRaw: amount,
},
],
}
})
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not a blocker but i think you might have been able to use the transfer movements of the protocol token

    const movements = await this.helpers.getErc20Movements({
      protocolToken: underlyingLpToken,

      filter: {
        fromBlock,
        toBlock,
        from: userAddress,
        to: protocolTokenAddress,
      },
    })

Copy link
Collaborator

Choose a reason for hiding this comment

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

We have a helper

Copy link
Collaborator

Choose a reason for hiding this comment

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

but please dont bother to update its not worth it

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

100% worth it if we have a helper. I'll update.

Comment on lines +191 to +200
const lpStakingContract =
protocolToken.lpStakingType === 'LpStaking'
? LpStaking__factory.connect(
protocolToken.lpStakingAddress,
this.provider,
)
: LpStakingTime__factory.connect(
protocolToken.lpStakingAddress,
this.provider,
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is fine for now but what stopped you doing a separate adapter?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It was my initial thought, since it looked that some chains used one contract and some the other. So my plan was to make a common adapter and then extend for the very tiny different bits.

Then I saw that some chains (mainnet) used both depending on the pool.

Overall, it's a question of whether these ifs are annoying enough to justify a whole new adapter that will either have almost identical code or an abstraction with then several bits of code in protected functions reimplemented for each type.

No strong opinion either way, it's a grey area.

Comment on lines +342 to +345
/**
* There are no specific events for rewards, which occur as simple transfers whenever a Deposit or Withdrawal is actioned
* For this reason, we need to fetch all Deposit and Withdrawal events and then filter out the reward transfers
*/
Copy link
Collaborator

Choose a reason for hiding this comment

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

These are the type of scenarios, among others, are the reason why I dont want us to rule out having an indexer....hence why I want @xavier-brochard to at least explorer the indexer solution for ETH2

Comment on lines +366 to +370
const depositFilter = lpStakingContract.filters.Deposit(
userAddress,
protocolToken.poolIndex,
undefined,
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just to confirm are you saying rewards can be "claimed" even with deposits?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, rewards get automatically claimed whenever user deposits or withdraws. They don't seem to have a method to claim them directly.
image

Comment on lines +23 to +36
// Copies lodash implementation of kebabCase and modifies it to treat version numbers as a single word
function kebabCase(input: string) {
return words(lodashToString(input).replace(/['\u2019]/g, '')).reduce(
(result, word, index, wordSplit) => {
const useHyphen =
index &&
!(wordSplit[index - 1]!.toLowerCase() === 'v' && /^\d+$/.test(word))

return result + (useHyphen ? '-' : '') + word.toLowerCase()
},
'',
)
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

nice thank you

Comment on lines +25 to +35
{
"address": "0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6",
"name": "StargateToken",
"symbol": "STG",
"decimals": 18,
"type": "underlying",
"blockNumber": 20661441,
"balanceRaw": "29168188478059884180158n",
"price": 0.27636857144740007,
"balance": 29168.188478059885
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

is this a claimed rewards? If so is the type correct? I think it should it be underlying-claimable?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I thought so too. But every other adapter implementing the getRewardWithdrawals returns them as underlying, so I used this for consistency.

name: rewardToken.name,
symbol: rewardToken.symbol,
decimals: rewardToken.decimals,
type: TokenType.Underlying,
Copy link
Collaborator

Choose a reason for hiding this comment

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

underlying-claimable

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

As mentioned before. I'm using the same type that other getRewardWithdrawals implementations (curve and convex) use.

Maybe we need to change them all.

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.

2 participants