Skip to content

Commit

Permalink
Bean UI: Seed Gauge System Changes (#725)
Browse files Browse the repository at this point in the history
  • Loading branch information
uncoolzero authored May 22, 2024
2 parents 49101d6 + 61d1f8e commit d506bf7
Show file tree
Hide file tree
Showing 121 changed files with 160,122 additions and 140,285 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.subgraph-basin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
types: [opened, synchronize]
paths:
- "projects/subgraph-basin/**"
- "projects/subgraph-core/**"

jobs:
compile:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.subgraph-bean.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
types: [opened, synchronize]
paths:
- "projects/subgraph-bean/**"
- "projects/subgraph-core/**"

jobs:
compile:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.subgraph-beanft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
types: [opened, synchronize]
paths:
- "projects/subgraph-beanft/**"
- "projects/subgraph-core/**"

jobs:
compile:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.subgraph-beanstalk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
types: [opened, synchronize]
paths:
- "projects/subgraph-beanstalk/**"
- "projects/subgraph-core/**"

jobs:
compile:
Expand Down
2 changes: 1 addition & 1 deletion projects/cli/src/commands/setbalance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const setbalance = async (sdk, chain, { account, symbol, amount }) => {
if (!symbol) {
await chain.setAllBalances(account, amount);
} else {
const symbols = ["ETH", "WETH", "BEAN", "USDT", "USDC", "DAI", "3CRV", "BEAN3CRV", "BEANWETH", "urBEAN", "urBEANWETH", "ROOT"];
const symbols = ["ETH", "WETH", "BEAN", "USDT", "USDC", "DAI", "CRV3", "BEAN3CRV", "BEANWETH", "urBEAN", "urBEANWETH", "ROOT"];
if (!symbols.includes(symbol)) {
console.log(`${chalk.bold.red("Error")} - ${chalk.bold.white(symbol)} is not a valid token. Valid options are: `);
console.log(symbols.map((s) => chalk.green(s)).join(", "));
Expand Down
20 changes: 13 additions & 7 deletions projects/examples/src/silo/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,28 @@ main().catch((e) => {
console.log(e);
});

let sdk:BeanstalkSDK;
let sdk: BeanstalkSDK;

async function main() {
const account = process.argv[3] || _account;
console.log(`${chalk.bold.whiteBright("Account:")} ${chalk.greenBright(account)}`);
let { sdk: _sdk, stop } = await impersonate(account);
sdk = _sdk;
sdk.DEBUG = false;
await sdk.refresh();
// const fromToken = sdk.tokens.UNRIPE_BEAN_WETH;
// const toToken = sdk.tokens.BEAN_ETH_WELL_LP;
const fromToken = sdk.tokens.UNRIPE_BEAN;
const toToken = sdk.tokens.BEAN;


const fromToken = sdk.tokens.BEAN
const toToken = sdk.tokens.UNRIPE_BEAN
const amount = fromToken.amount(2500)
const maxConvert = await sdk.contracts.beanstalk.getMaxAmountIn(fromToken.address, toToken.address);

let tx = await sdk.silo.convert(fromToken, toToken, amount)
const amount = fromToken.amount(1000);
const quote = await sdk.contracts.beanstalk.getAmountOut(fromToken.address, toToken.address, amount.toBlockchain());
console.log(quote.toString());

let tx = await sdk.silo.convert(fromToken, toToken, amount);
await tx.wait();

await stop();
}
6 changes: 4 additions & 2 deletions projects/sdk/src/classes/Token/Token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ declare module "@beanstalk/sdk-core" {
abstract class Token {
static _source: string;
isUnripe: boolean;
rewards?: { stalk: TokenValue; seeds: TokenValue };
rewards?: { stalk: TokenValue; seeds: TokenValue | null };
getStalk(bdv?: TokenValue): TokenValue;
getSeeds(bdv?: TokenValue): TokenValue;
approveBeanstalk(amount: TokenValue | BigNumber): Promise<ContractTransaction>;
Expand All @@ -34,7 +34,9 @@ CoreToken.prototype.getStalk = function (bdv?: TokenValue): TokenValue {
* Get the amount of Seeds rewarded per deposited BDV of this Token.
* */
CoreToken.prototype.getSeeds = function (bdv?: TokenValue): TokenValue {
if (!this.rewards?.seeds) return TokenValue.fromHuman(0, SEED_DECIMALS);
if (this.rewards?.seeds === undefined || this.rewards.seeds === null) {
throw new Error(`Token ${this.symbol} has no seeds defined!`);
}
if (!bdv) return this.rewards.seeds;

return this.rewards.seeds.mul(bdv);
Expand Down
15 changes: 15 additions & 0 deletions projects/sdk/src/lib/BeanstalkSDK.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export class BeanstalkSDK {
public providerOrSigner: Signer | Provider;
public source: DataSource;
public subgraphUrl: string;
public lastRefreshTimestamp: number;

public readonly chainId: ChainId;
public readonly addresses: typeof addresses;
Expand Down Expand Up @@ -99,6 +100,19 @@ export class BeanstalkSDK {
this.wells = new WellsSDK(config);
}

/**
* Refreshes the SDK's state with updated data from contracts. This should be called immediately after sdk initialization and after every season
*/
async refresh() {
// Reload dynamic stalk per wl token
const whitelist = this.tokens.siloWhitelist;
for await (const token of whitelist) {
const { stalkEarnedPerSeason } = await this.contracts.beanstalk.tokenSettings(token.address);
token.rewards!.seeds = this.tokens.SEEDS.fromBlockchain(stalkEarnedPerSeason);
}
this.lastRefreshTimestamp = Date.now();
}

debug(...args: any[]) {
if (!this.DEBUG) return;
console.debug(...args);
Expand Down Expand Up @@ -167,6 +181,7 @@ export class BeanstalkSDK {
toJSON() {
return {
chainId: this.chainId,
lastRefreshTimestamp: this.lastRefreshTimestamp,
provider: {
url: this.provider?.connection?.url,
network: this.provider?._network
Expand Down
25 changes: 14 additions & 11 deletions projects/sdk/src/lib/events/processor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ const account = "0xFARMER";
* and not the indices; this is more for consistency.
*/
const propArray = (o: { [key: string]: any }) =>
Object.keys(o).reduce((prev, key) => {
prev[prev.length] = o[key];
prev[key] = o[key];
return prev;
}, [] as (keyof typeof o)[] & typeof o);
Object.keys(o).reduce(
(prev, key) => {
prev[prev.length] = o[key];
prev[key] = o[key];
return prev;
},
[] as (keyof typeof o)[] & typeof o
);

const mockProcessor = () => new EventProcessor(sdk, account);

Expand Down Expand Up @@ -205,8 +208,8 @@ describe("the Silo", () => {
bdv: bdv1
})
} as AddDepositEvent);

expect(p.deposits.get(Bean)?.["6074"]).toStrictEqual({
const t = p.deposits.get(Bean);
expect(p.deposits.get(Bean)?.["6074000000"]).toStrictEqual({
amount: amount1,
bdv: bdv1
});
Expand All @@ -225,7 +228,7 @@ describe("the Silo", () => {
})
} as AddDepositEvent);

expect(p.deposits.get(Bean)?.["6074"]).toStrictEqual({
expect(p.deposits.get(Bean)?.["6074000000"]).toStrictEqual({
amount: amount1.add(amount2),
bdv: bdv1.add(bdv2)
});
Expand All @@ -244,7 +247,7 @@ describe("the Silo", () => {
})
} as AddDepositEvent);

expect(p.deposits.get(BeanCrv3)?.["6100"]).toStrictEqual({
expect(p.deposits.get(BeanCrv3)?.["6100000000"]).toStrictEqual({
amount: amount3,
bdv: bdv3
});
Expand Down Expand Up @@ -281,7 +284,7 @@ describe("the Silo", () => {
})
} as RemoveDepositEvent);

expect(p.deposits.get(Bean)?.["6074"]).toStrictEqual({
expect(p.deposits.get(Bean)?.["6074000000"]).toStrictEqual({
amount: amount1.sub(amount2),
bdv: bdv1.sub(bdv2)
});
Expand All @@ -300,7 +303,7 @@ describe("the Silo", () => {
})
} as RemoveDepositEvent);

expect(p.deposits.get(Bean)?.["6074"]).toBeUndefined();
expect(p.deposits.get(Bean)?.["6074000000"]).toBeUndefined();
});
});

Expand Down
15 changes: 12 additions & 3 deletions projects/sdk/src/lib/events/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import { BeanstalkSDK } from "../BeanstalkSDK";
import { EventManager } from "src/lib/events/EventManager";
import { ZERO_BN } from "src/constants";
import { TokenValue } from "@beanstalk/sdk-core";

// ----------------------------------------

Expand Down Expand Up @@ -394,7 +395,7 @@ export class EventProcessor {

AddDeposit(event: EventManager.Simplify<AddDepositEvent>) {
const token = this.getToken(event);
const stem = event.args.stem.toString();
const stem = this.migrateStem(event.args.stem);

if (!this.whitelist.has(token)) throw new Error(`Attempted to process an event with an unknown token: ${token}`);

Expand All @@ -407,14 +408,22 @@ export class EventProcessor {

RemoveDeposit(event: EventManager.Simplify<RemoveDepositEvent>) {
const token = this.getToken(event);
const stem = event.args.stem.toString();
const stem = this.migrateStem(event.args.stem);
this._removeDeposit(stem, token, event.args.amount);
}

RemoveDeposits(event: EventManager.Simplify<RemoveDepositsEvent>) {
const token = this.getToken(event);
event.args.stems.forEach((stem, index) => {
this._removeDeposit(stem.toString(), token, event.args.amounts[index]);
this._removeDeposit(this.migrateStem(stem), token, event.args.amounts[index]);
});
}

migrateStem(stem: ethers.BigNumber): string {
let stemTV = TokenValue.fromBlockchain(stem, 0);
if (stemTV.abs().lt(10 ** 6)) stemTV = stemTV.mul(10 ** 6);
const migratedStem = stemTV.toHuman();

return migratedStem;
}
}
25 changes: 0 additions & 25 deletions projects/sdk/src/lib/root.test.ts

This file was deleted.

44 changes: 31 additions & 13 deletions projects/sdk/src/lib/silo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,11 @@ export class Silo {
options?: { source: DataSource.LEDGER } | { source: DataSource.SUBGRAPH }
): Promise<TokenSiloBalance> {
const source = Silo.sdk.deriveConfig("source", options);
const [account, currentSeason, stemTip] = await Promise.all([
const [account, currentSeason, stemTip, germinatingStem] = await Promise.all([
Silo.sdk.getAccount(_account),
Silo.sdk.sun.getSeason(),
this.getStemTip(_token)
this.getStemTip(_token),
Silo.sdk.contracts.beanstalk.getGerminatingStem(_token.address)
]);

if (!Silo.sdk.tokens.siloWhitelist.has(_token)) throw new Error(`${_token.address} is not whitelisted in the Silo`);
Expand All @@ -212,7 +213,8 @@ export class Silo {
utils.applyDeposit(balance, _token, stemTip, {
stem,
amount: deposits[stem].amount,
bdv: deposits[stem].bdv
bdv: deposits[stem].bdv,
germinatingStem
});
}

Expand All @@ -237,7 +239,8 @@ export class Silo {
utils.applyDeposit(balance, _token, stemTip, {
stem: deposit.season, // FIXME
amount: deposit.amount,
bdv: deposit.bdv
bdv: deposit.bdv,
germinatingStem
})
);

Expand All @@ -262,17 +265,25 @@ export class Silo {
_account?: string,
options?: { source: DataSource.LEDGER } | { source: DataSource.SUBGRAPH }
): Promise<Map<Token, TokenSiloBalance>> {
/// SETUP
const whitelist = Silo.sdk.tokens.siloWhitelist;
const whiteListTokens = Array.from(whitelist);
const balances = new Map<Token, TokenSiloBalance>();
whitelist.forEach((token) => balances.set(token, utils.makeTokenSiloBalance()));
const source = Silo.sdk.deriveConfig("source", options);
const [account, currentSeason, stemTips] = await Promise.all([

const [account, currentSeason, stemTips, germinatingStemsRaw] = await Promise.all([
Silo.sdk.getAccount(_account),
Silo.sdk.sun.getSeason(),
this.getStemTips([...Silo.sdk.tokens.siloWhitelist])
this.getStemTips([...Silo.sdk.tokens.siloWhitelist]),
Silo.sdk.contracts.beanstalk.getGerminatingStems(whiteListTokens.map((t) => t.address))
]);

/// SETUP
const whitelist = Silo.sdk.tokens.siloWhitelist;
const balances = new Map<Token, TokenSiloBalance>();
whitelist.forEach((token) => balances.set(token, utils.makeTokenSiloBalance()));
// Set germinatingStems
const germinatingStems = new Map<Token, BigNumber>();
for (let i = 0; i < germinatingStemsRaw.length; i++) {
germinatingStems.set(whiteListTokens[i], germinatingStemsRaw[i]);
}

/// LEDGER
if (source === DataSource.LEDGER) {
Expand All @@ -283,6 +294,9 @@ export class Silo {
// Handle deposits.
// Attach stalk & seed counts for each crate.
depositsByToken.forEach((deposits, token) => {
const germinatingStem = germinatingStems.get(token)!;
if (!germinatingStem) throw new Error(`No germinatingStem found for ${token.symbol}`);

// If we receive a token that wasn't on the SDK's known whitelist, create
// a new balance object for it. (This shouldn't happen)
if (!balances.has(token)) balances.set(token, utils.makeTokenSiloBalance());
Expand All @@ -296,7 +310,8 @@ export class Silo {
utils.applyDeposit(balance, token, stemTip, {
stem,
amount: deposits[stem].amount,
bdv: deposits[stem].bdv
bdv: deposits[stem].bdv,
germinatingStem
});
}

Expand All @@ -319,9 +334,11 @@ export class Silo {
const { deposited } = query.farmer;

// Handle deposits.
deposited.forEach((deposit: typeof deposited[number]) => {
deposited.forEach((deposit: (typeof deposited)[number]) => {
const token = Silo.sdk.tokens.findByAddress(deposit.token);
if (!token) return; // FIXME: unknown token handling
const germinatingStem = germinatingStems.get(token)!;
if (!germinatingStem) throw new Error(`No germinatingStem found for ${token.symbol}`);

// If we receive a token that wasn't on the SDK's known whitelist, create
// a new balance object for it. (This shouldn't happen)
Expand All @@ -335,7 +352,8 @@ export class Silo {
utils.applyDeposit(balance, token, stemTip, {
stem: deposit.stem || deposit.season,
amount: deposit.amount,
bdv: deposit.bdv
bdv: deposit.bdv,
germinatingStem
});
});

Expand Down
Loading

0 comments on commit d506bf7

Please sign in to comment.