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

Add Wido Zaps with support for more vaults #306

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@
"cross-fetch": "3.1.5",
"dotenv": "10.0.0",
"emittery": "0.8.1",
"type-fest": "1.2.1"
"type-fest": "1.2.1",
"wido": "^0.0.31"
},
"size-limit": [
{
Expand Down
1 change: 1 addition & 0 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export enum ContractAddressId {
portalsZapIn = "PORTALS_ZAP_IN",
portalsZapOut = "PORTALS_ZAP_OUT",
pickleZapIn = "PICKLE_ZAP_IN",
widoZapRouter = "WIDO_ZAP_ROUTER",
xgambitox marked this conversation as resolved.
Show resolved Hide resolved
propertiesAggregator = "PROPERTIES_AGGREGATOR",
gaugeRegistry = "GAUGE_REGISTRY",
claimRewardsZap = "CLAIM_REWARDS_ZAP",
Expand Down
22 changes: 22 additions & 0 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { PartialDeep } from "type-fest";

import { Address, Locale, SdkError } from "./types";
import { encode } from "./utils";
import { ZapInWith, ZapOutWith } from "./zap";

export interface AddressesOverride {
lens?: Address;
Expand Down Expand Up @@ -53,6 +54,11 @@ export interface SubgraphConfiguration {
optimismSubgraphEndpoint?: string;
}

export interface ZapsConfiguration {
zapInWith: ZapInWith[];
zapOutWith: ZapOutWith[];
}

/**
* Context options that are used to access all the data sources queried by the
* SDK.
Expand All @@ -67,6 +73,7 @@ export interface ContextValue {
subgraph?: SubgraphConfiguration;
partnerId?: string;
locale?: Locale;
zaps?: ZapsConfiguration;
env?: "production" | "development";
}

Expand All @@ -77,6 +84,10 @@ const DefaultContext: ContextValue = {
// The default tenderly dashboard for Yearn
simulation: { dashboardUrl: "https://dashboard.tenderly.co/yearn/yearn-web" },
cache: { useCache: true, url: "https://cache.yearn.finance" },
zaps: {
zapInWith: ["widoZapIn", "portalsZapIn"],
zapOutWith: ["widoZapOut", "portalsZapOut"],
},
env: "production",
};

Expand Down Expand Up @@ -163,6 +174,17 @@ export class Context implements ContextValue {
return this.ctx.locale || "en";
}

get zaps(): ZapsConfiguration {
return this.ctx.zaps || (DefaultContext.zaps as ZapsConfiguration);
}

get isZapsDefault(): boolean {
return (
this.ctx.zaps?.zapInWith === DefaultContext.zaps?.zapInWith &&
this.ctx.zaps?.zapOutWith === DefaultContext.zaps?.zapOutWith
);
}

get isDevelopment(): boolean {
return this.ctx.env !== "production";
}
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "./mergeZapPropsWithAddressables";
export * from "./mergeZapPropsWithZappables";
60 changes: 0 additions & 60 deletions src/interfaces/helpers/mergeZapPropsWithAddressables.spec.ts

This file was deleted.

42 changes: 0 additions & 42 deletions src/interfaces/helpers/mergeZapPropsWithAddressables.ts

This file was deleted.

109 changes: 109 additions & 0 deletions src/interfaces/helpers/mergeZapPropsWithZappables.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { createMockTokenMarketData, createMockVaultMetadata } from "../../test-utils/factories";
import { mergeZapInPropsWithZappables, mergeZapOutPropsWithZappables } from "./mergeZapPropsWithZappables";

describe("mergeZapInPropsWithZappables", () => {
it("should set the zap in properties on an zappable", async () => {
const vaultMetadataMock = {
zappable: createMockVaultMetadata({
displayName: "Zappable",
address: "0x16de59092dae5ccf4a1e6439d611fd0653f0bd01", // not checksummed
allowZapIn: false,
}),
notZappable: createMockVaultMetadata({
displayName: "Not Zappable",
address: "0x6B175474E89094C44Da98b954EedeAC495271d0F",
allowZapIn: false,
}),
};

const vaultTokenMarketDataMock = {
zappable: createMockTokenMarketData({
label: "Zappable",
address: "0x16de59092dAE5CcF4A1E6439D611fd0653f0Bd01", // checksummed
}),
notInVaults: createMockTokenMarketData({
label: "Not in Vaults",
address: "0xd6aD7a6750A7593E092a9B218d66C0A814a3436e",
}),
random: createMockTokenMarketData({ label: "Random", address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" }),
};

const actual = mergeZapInPropsWithZappables({
zappables: [vaultMetadataMock.zappable, vaultMetadataMock.notZappable],
supportedVaultAddresses: [
vaultTokenMarketDataMock.zappable.address,
vaultTokenMarketDataMock.notInVaults.address,
vaultTokenMarketDataMock.random.address,
],
zapInType: "zapperZapIn",
});

expect(actual.length).toEqual(2);
expect(actual).toEqual(
expect.arrayContaining([
{
...vaultMetadataMock.zappable,
allowZapIn: true,
zapInWith: "zapperZapIn",
},
{
...vaultMetadataMock.notZappable,
allowZapIn: false,
zapInWith: undefined,
},
])
);
});
it("should set the zap out properties on an zappable", async () => {
const vaultMetadataMock = {
zappable: createMockVaultMetadata({
displayName: "Zappable",
address: "0x16de59092dae5ccf4a1e6439d611fd0653f0bd01", // not checksummed
allowZapOut: false,
}),
notZappable: createMockVaultMetadata({
displayName: "Not Zappable",
address: "0x6B175474E89094C44Da98b954EedeAC495271d0F",
allowZapOut: false,
}),
};

const vaultTokenMarketDataMock = {
zappable: createMockTokenMarketData({
label: "Zappable",
address: "0x16de59092dAE5CcF4A1E6439D611fd0653f0Bd01", // checksummed
}),
notInVaults: createMockTokenMarketData({
label: "Not in Vaults",
address: "0xd6aD7a6750A7593E092a9B218d66C0A814a3436e",
}),
random: createMockTokenMarketData({ label: "Random", address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" }),
};

const actual = mergeZapOutPropsWithZappables({
zappables: [vaultMetadataMock.zappable, vaultMetadataMock.notZappable],
supportedVaultAddresses: [
vaultTokenMarketDataMock.zappable.address,
vaultTokenMarketDataMock.notInVaults.address,
vaultTokenMarketDataMock.random.address,
],
zapOutType: "zapperZapOut",
});

expect(actual.length).toEqual(2);
expect(actual).toEqual(
expect.arrayContaining([
{
...vaultMetadataMock.zappable,
allowZapOut: true,
zapOutWith: "zapperZapOut",
},
{
...vaultMetadataMock.notZappable,
allowZapOut: false,
zapOutWith: undefined,
},
])
);
});
});
84 changes: 84 additions & 0 deletions src/interfaces/helpers/mergeZapPropsWithZappables.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { getAddress } from "@ethersproject/address";

import { Address, Addressable, Token } from "../../types";

type Zappable = Addressable & {
allowZapIn?: boolean;
allowZapOut?: boolean;
zapInWith?: string;
zapOutWith?: string;
};

type MergeZapInPropsWithZappables<T> = {
zappables: T[];
supportedVaultAddresses: Address[];
zapInType: keyof Token["supported"];
};

type MergeZapOutPropsWithZappables<T> = {
zappables: T[];
supportedVaultAddresses: Address[];
zapOutType: keyof Token["supported"];
};

/**
* Helper function to set the zap properties on an Addressable
* @param zappables an array of objects with an address prop
* @param supportedVaultAddresses the supported vault addresses
* @returns the updated metadata
*/
export function mergeZapInPropsWithZappables<T extends Zappable>({
zappables,
supportedVaultAddresses,
zapInType,
}: MergeZapInPropsWithZappables<T>): T[] {
const supportedVaultAddressesSet = new Set(supportedVaultAddresses);

return zappables.map((zappable) => {
if (zappable.zapInWith) return zappable;

try {
const address = getAddress(zappable.address);
const isZappable = supportedVaultAddressesSet.has(address);

return {
...zappable,
allowZapIn: isZappable,
zapInWith: isZappable ? zapInType : undefined,
};
} catch (error) {
return zappable;
}
});
}

/**
* Helper function to set the zap properties on an Addressable
* @param zappables an array of objects with an address prop
* @param supportedVaultAddresses the supported vault addresses
* @returns the updated metadata
*/
export function mergeZapOutPropsWithZappables<T extends Zappable>({
zappables,
supportedVaultAddresses,
zapOutType,
}: MergeZapOutPropsWithZappables<T>): T[] {
const supportedVaultAddressesSet = new Set(supportedVaultAddresses);

return zappables.map((zappable) => {
if (zappable.zapOutWith) return zappable;

try {
const address = getAddress(zappable.address);
const isZappable = supportedVaultAddressesSet.has(address);

return {
...zappable,
allowZapOut: isZappable,
zapOutWith: isZappable ? zapOutType : undefined,
};
} catch (error) {
return zappable;
}
});
}
Loading