Skip to content

Add Yielder crate#816

Open
0xh3rman wants to merge 59 commits intomainfrom
yielder
Open

Add Yielder crate#816
0xh3rman wants to merge 59 commits intomainfrom
yielder

Conversation

@0xh3rman
Copy link
Collaborator

@0xh3rman 0xh3rman commented Nov 29, 2025

Summary

  • Introduce the new yielder crate and Yo yield provider (yoUSD on Base, yoUSDT on Ethereum) with on-chain APY/position data, Yo API rewards, and deposit/withdraw tx builders with approval handling.
  • Expose yield to mobile via Gemstone: GemYielder UniFFI object + types, yield transaction helpers, and gateway auto-filling yield call data when missing.
  • Extend core primitives/transaction pipeline for yield (YieldAction/YieldData/EvmYieldData, TransactionInputType::Yield, TransactionType YieldDeposit/Withdraw, BannerEvent::Yield) and wire yield handling into fee/preload logic across chains.
  • Refactor EVM multicall3 for block-scoped batching + timestamp calls; use it for Yo lookback pricing and Everstake account state, plus minor RPC/decoder tweaks.

Testing

  • Not run (description update only).
  • Added yielder integration tests behind the yield_integration_tests feature.

Checklist

  • Verify Everstake account state via multicall (deposited/pending/pending-deposited/withdraw/restaked) on Ethereum.
  • Verify Yo yields with APY on Base and Ethereum.
  • Verify Yo positions include rewards from Yo API.
  • Verify yield deposit/withdraw tx build flows (approval required vs not required).
  • Verify multicall at historical block + timestamp returns expected values.

@semanticdiff-com
Copy link

semanticdiff-com bot commented Nov 29, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  crates/gem_aptos/src/rpc/client.rs  91% smaller
  crates/primitives/src/transaction_load_metadata.rs  86% smaller
  crates/gem_cosmos/src/provider/preload_mapper.rs  85% smaller
  crates/gem_solana/src/provider/preload_mapper.rs  85% smaller
  crates/gem_sui/src/provider/preload_mapper.rs  81% smaller
  crates/swapper/src/near_intents/provider.rs  74% smaller
  gemstone/src/gateway/error.rs  72% smaller
  crates/primitives/src/transaction.rs  68% smaller
  crates/swapper/src/proxy/provider.rs  63% smaller
  crates/swapper/src/jupiter/provider.rs  56% smaller
  crates/gem_evm/src/rpc/client.rs  54% smaller
  bin/gas-bench/src/client.rs  54% smaller
  crates/gem_evm/src/call_decoder.rs  44% smaller
  gemstone/src/alien/error.rs  43% smaller
  crates/primitives/src/asset_metadata.rs  36% smaller
  crates/gem_hypercore/src/signer/core_signer.rs  36% smaller
  crates/swapper/src/thorchain/provider.rs  35% smaller
  crates/gem_evm/src/provider/preload.rs  33% smaller
  crates/gem_evm/src/everstake/client.rs  31% smaller
  crates/swapper/src/across/provider.rs  27% smaller
  crates/gem_jsonrpc/src/native_provider/reqwest.rs  24% smaller
  gemstone/src/models/transaction.rs  14% smaller
  crates/gem_evm/src/contracts/erc20.rs  14% smaller
  crates/gem_evm/src/provider/preload_mapper.rs  13% smaller
  gemstone/tests/ios/GemTest/GemTest/Networking/Provider.swift  12% smaller
  gemstone/tests/ios/GemTest/GemTest/Extension/Gemstone+Extension.swift  12% smaller
  gemstone/src/gateway/mod.rs  12% smaller
  crates/swapper/src/chainflip/provider.rs  11% smaller
  crates/gem_evm/src/multicall3.rs  5% smaller
  crates/swapper/src/thorchain/mod.rs  3% smaller
  bin/gas-bench/src/solana_client.rs  3% smaller
  crates/swapper/src/alien/mod.rs  3% smaller
  crates/swapper/src/client_factory.rs  2% smaller
  gemstone/src/alien/reqwest_provider.rs  2% smaller
  crates/gem_sui/src/provider/staking_mapper.rs  1% smaller
  crates/swapper/src/uniswap/v4/provider.rs  1% smaller
  crates/gem_tron/src/provider/staking_mapper.rs  1% smaller
  gemstone/src/models/stake.rs  1% smaller
  AGENTS.md Unsupported file format
  Cargo.lock Unsupported file format
  Cargo.toml Unsupported file format
  apps/daemon/src/pusher/pusher.rs  0% smaller
  bin/gas-bench/src/main.rs  0% smaller
  crates/gem_aptos/src/provider/staking_mapper.rs  0% smaller
  crates/gem_cosmos/src/provider/staking_mapper.rs  0% smaller
  crates/gem_evm/src/lib.rs  0% smaller
  crates/gem_evm/src/provider/staking_ethereum.rs  0% smaller
  crates/gem_evm/src/provider/staking_monad.rs  0% smaller
  crates/gem_evm/src/provider/staking_smartchain.rs  0% smaller
  crates/gem_evm/src/u256.rs  0% smaller
  crates/gem_hypercore/src/provider/staking_mapper.rs  0% smaller
  crates/gem_jsonrpc/src/lib.rs  0% smaller
  crates/gem_jsonrpc/src/native_provider/mod.rs  0% smaller
  crates/gem_solana/src/provider/staking_mapper.rs  0% smaller
  crates/gem_tron/src/provider/balances_mapper.rs  0% smaller
  crates/gem_tron/src/provider/preload_mapper.rs  0% smaller
  crates/primitives/src/asset_balance.rs  0% smaller
  crates/primitives/src/balance_type.rs  0% smaller
  crates/primitives/src/banner.rs  0% smaller
  crates/primitives/src/delegation.rs  0% smaller
  crates/primitives/src/earn_data.rs  0% smaller
  crates/primitives/src/earn_provider.rs  0% smaller
  crates/primitives/src/earn_type.rs  0% smaller
  crates/primitives/src/hex.rs  0% smaller
  crates/primitives/src/lib.rs  0% smaller
  crates/primitives/src/swap/approval.rs  0% smaller
  crates/primitives/src/testkit/delegation_mock.rs  0% smaller
  crates/primitives/src/transaction_input_type.rs  0% smaller
  crates/primitives/src/transaction_type.rs  0% smaller
  crates/swapper/src/alien/error.rs  0% smaller
  crates/swapper/src/approval/evm.rs  0% smaller
  crates/swapper/src/error.rs  0% smaller
  crates/swapper/src/hyperliquid/provider/spot/provider.rs  0% smaller
  crates/swapper/src/lib.rs  0% smaller
  crates/swapper/src/swapper.rs  0% smaller
  crates/swapper/src/thorchain/bigint.rs  0% smaller
  crates/yielder/Cargo.toml Unsupported file format
  crates/yielder/src/lib.rs  0% smaller
  crates/yielder/src/models.rs  0% smaller
  crates/yielder/src/provider.rs  0% smaller
  crates/yielder/src/yo/client.rs  0% smaller
  crates/yielder/src/yo/contract.rs  0% smaller
  crates/yielder/src/yo/error.rs  0% smaller
  crates/yielder/src/yo/mod.rs  0% smaller
  crates/yielder/src/yo/model.rs  0% smaller
  crates/yielder/src/yo/provider.rs  0% smaller
  crates/yielder/src/yo/vault.rs  0% smaller
  crates/yielder/tests/integration_test.rs  0% smaller
  gemstone/Cargo.toml Unsupported file format
  gemstone/android/gemstone/src/androidTest/java/com/gemwallet/gemstone/GemstoneTest.kt Unsupported file format
  gemstone/src/gem_yielder/mod.rs  0% smaller
  gemstone/src/gem_yielder/remote_types.rs  0% smaller
  gemstone/src/lib.rs  0% smaller
  gemstone/src/models/balance.rs  0% smaller
  gemstone/src/models/mod.rs  0% smaller

Refactored multicall3 to provide a builder-based batch interface with typed result decoding, replacing manual call construction and decoding in everstake and yielder modules. Added efficient position data fetching in YoGatewayClient using multicall batching for balances and historical prices, and updated YoYieldProvider to use this for APY and position queries. Added integration test for YoVault positions. Improved error handling and re-exported PositionData.
Introduces an is_yield_available method to Yielder and GemYielder for checking if yield is available for a given asset. Also corrects asset value calculation in YoYieldProvider to derive it from share balance and latest price.
@0xh3rman 0xh3rman marked this pull request as ready for review January 14, 2026 04:55
Refactored YoYieldProvider to support multiple chains by managing gateways per chain and updating vault definitions. Added USDT vault for Ethereum, replaced YO_GATEWAY_BASE_MAINNET with YO_GATEWAY, and updated GemYielder to initialize gateways for both Base and Ethereum chains. Adjusted lookback block calculation and related logic to be chain-aware.
0xh3rman and others added 28 commits January 26, 2026 11:14
Replace the legacy Yield types with Earn equivalents across the codebase: TransactionInputType::Yield -> TransactionInputType::Earn and YieldAction -> EarnAction. Add new primitives (earn_action, earn_data, earn_position, earn_provider) and remove the old yield_data. Update providers, preload mappers, RPC clients, yielder implementation and tests to use the new Earn types and BigInt values where appropriate. Adjust Uniffi remote types in gemstone to GemEarn* and use GemBigInt for position balances. Add num-bigint dependency to Cargo and yielder Cargo.toml. Misc: small formatting/unwrap fixes in yielder client code and gas/fee mappings updated to reference Earn variants.
 - Add `earn` field to Balance/GemBalance structs
  - Add `get_balance_earn`, `get_earn_providers`, `get_earn_positions` to GemGateway
  - Move concurrent position fetching into Yielder.positions_for_chain()
  - Add yields_for_chain() to YieldProviderClient trait and YoYieldProvider
  - Make build_yielder infallible (gracefully skip unavailable chains)
  - Remove GemYielder FFI wrapper (all earn operations now go through GemGateway)
  - Remove GemEarnTransaction, GemEarnTransactionData remote types (unused)
  - Remove dead code: Yielder.yields_for_asset()
Resolved conflicts in:
- AGENTS.md: Adopted updated testing guidelines from main
- gemstone/src/gateway/mod.rs: Used with_provider pattern for consistency
- NativeProvider.kt: Updated error type to AlienException.RequestException

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Remove duplicate encode_with_0x function in hex.rs
- Add missing StakeData import in gemstone transaction models
let withdraw_request = results.decode::<IAccounting::withdrawRequestCall>(&withdraw)?;
let restaked_reward = results
.decode::<IAccounting::restakedRewardOfCall>(&restaked)
.map(u256_to_biguint)
Copy link
Contributor

Choose a reason for hiding this comment

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

is it possible to avoid u256_to_biguint and unwrap?

_ => Err("Unsupported chain for staking".into()),
},
TransactionInputType::Earn(_, _) => {
let earn_data = match &input.metadata {
Copy link
Contributor

Choose a reason for hiding this comment

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

&input.metadata.get_data() we might have this already?

if let Some(approval) = &earn_data.approval {
Ok(TransactionParams::new(approval.token.clone(), encode_erc20_approve(&approval.spender)?, BigInt::from(0)))
} else {
let call_data = earn_data.call_data.as_ref().ok_or("Missing call_data")?;
Copy link
Contributor

Choose a reason for hiding this comment

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

why call data would be missing?

}
}
TransactionInputType::Earn(_, _) => {
let earn_data = match &input.metadata {
Copy link
Contributor

Choose a reason for hiding this comment

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

same here &input.metadata.get_data()

_ => None,
};
if let Some(data) = earn_data
&& let Some(gas_limit) = data.gas_limit.as_ref()
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe as limit bigint?

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.

3 participants