Skip to content

Commit

Permalink
Merge branch 'main' into dev
Browse files Browse the repository at this point in the history
* main: (172 commits)
  fix: disabled pool-together-v3's TVL (Zapper-fi#824)
  chore(main): release 0.101.0 (Zapper-fi#819)
  feat: add pool ratio to statsItem (Zapper-fi#825)
  fix: filtered out maple pool positions without liquidity (Zapper-fi#823)
  fix: removed prefix from coslend positions label (Zapper-fi#822)
  feat(qi-dao): add arbitrum support (Zapper-fi#821)
  fix: refactor aurora-plus's helper making it injectable (Zapper-fi#818)
  chore(main): release 0.100.3 (Zapper-fi#816)
  fix: add aurora plus logo (Zapper-fi#817)
  fix: solace fix addresses and style (Zapper-fi#815)
  fix(global): Roll API key
  chore(main): release 0.100.2 (Zapper-fi#813)
  fix(curve): Fix Curve label for cases with a single app token like ibEUR / sEUR
  chore(main): release 0.100.1 (Zapper-fi#810)
  fix(curve): Adjust Curve labels, show Yearn yield tokens in explore (Zapper-fi#812)
  fix(vvs-finance): update vvs-finance name definition (Zapper-fi#811)
  fix(yearn): Fix vault displayed APY (Zapper-fi#809)
  chore(main): release 0.100.0 (Zapper-fi#807)
  fix(good-ghosting): Removed support for inactive games (Zapper-fi#806)
  fix(rari-fuse): Add missing Arrakis Finance dependency (Zapper-fi#808)
  ...
  • Loading branch information
jn-lp committed Jul 5, 2022
2 parents 51c29d3 + 9e1ac42 commit 04182b1
Show file tree
Hide file tree
Showing 623 changed files with 77,139 additions and 7,881 deletions.
93 changes: 93 additions & 0 deletions .all-contributorsrc
Expand Up @@ -388,6 +388,99 @@
"question",
"maintenance"
]
},
{
"login": "BluebitFinance",
"name": "BlueBit Finance",
"avatar_url": "https://avatars.githubusercontent.com/u/96361968?v=4",
"profile": "https://github.com/BluebitFinance",
"contributions": [
"code"
]
},
{
"login": "Clonescody",
"name": "Clonescody",
"avatar_url": "https://avatars.githubusercontent.com/u/6602520?v=4",
"profile": "https://github.com/Clonescody",
"contributions": [
"code"
]
},
{
"login": "the-emerald",
"name": "Emerald",
"avatar_url": "https://avatars.githubusercontent.com/u/12746683?v=4",
"profile": "https://anson-cheung.com/",
"contributions": [
"code"
]
},
{
"login": "evLorne",
"name": "EvLorne",
"avatar_url": "https://avatars.githubusercontent.com/u/101081187?v=4",
"profile": "https://github.com/evLorne",
"contributions": [
"code"
]
},
{
"login": "0xKratos",
"name": "Kratos",
"avatar_url": "https://avatars.githubusercontent.com/u/32628639?v=4",
"profile": "https://github.com/0xKratos",
"contributions": [
"code"
]
},
{
"login": "reganwrench",
"name": "reganwrench",
"avatar_url": "https://avatars.githubusercontent.com/u/98139806?v=4",
"profile": "https://github.com/reganwrench",
"contributions": [
"code"
]
},
{
"login": "scruffy-dev",
"name": "scruffy-dev",
"avatar_url": "https://avatars.githubusercontent.com/u/82269917?v=4",
"profile": "https://github.com/scruffy-dev",
"contributions": [
"code"
]
},
{
"login": "Emile-Filteau",
"name": "Émile Filteau-Tessier",
"avatar_url": "https://avatars.githubusercontent.com/u/1054341?v=4",
"profile": "https://github.com/Emile-Filteau",
"contributions": [
"code",
"question",
"maintenance"
]
},
{
"login": "SamIam-0x",
"name": "Sam | Zapper",
"avatar_url": "https://avatars.githubusercontent.com/u/43358952?v=4",
"profile": "https://github.com/SamIam-0x",
"contributions": [
"doc",
"question"
]
},
{
"login": "singlefinance",
"name": "Single Finance Lab",
"avatar_url": "https://avatars.githubusercontent.com/u/92788245?v=4",
"profile": "https://www.singlefinance.io/",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7
Expand Down
443 changes: 443 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

16 changes: 15 additions & 1 deletion README.md
Expand Up @@ -18,7 +18,7 @@
</div>

<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-40-orange.svg?style=flat-square)](#contributors-)
[![All Contributors](https://img.shields.io/badge/all_contributors-50-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->

## Description
Expand Down Expand Up @@ -192,6 +192,20 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center"><a href="https://github.com/oo-00"><img src="https://avatars.githubusercontent.com/u/29607330?v=4?s=64" width="64px;" alt=""/><br /><sub><b>oo-00</b></sub></a><br /><a href="https://github.com/Zapper-fi/studio/commits?author=oo-00" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/takao-aurigami"><img src="https://avatars.githubusercontent.com/u/102155128?v=4?s=64" width="64px;" alt=""/><br /><sub><b>takao-aurigami</b></sub></a><br /><a href="https://github.com/Zapper-fi/studio/commits?author=takao-aurigami" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/sebaudet26"><img src="https://avatars.githubusercontent.com/u/6855274?v=4?s=64" width="64px;" alt=""/><br /><sub><b>Sébastien Audet</b></sub></a><br /><a href="https://github.com/Zapper-fi/studio/commits?author=sebaudet26" title="Code">💻</a> <a href="#question-sebaudet26" title="Answering Questions">💬</a> <a href="#maintenance-sebaudet26" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/BluebitFinance"><img src="https://avatars.githubusercontent.com/u/96361968?v=4?s=64" width="64px;" alt=""/><br /><sub><b>BlueBit Finance</b></sub></a><br /><a href="https://github.com/Zapper-fi/studio/commits?author=BluebitFinance" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Clonescody"><img src="https://avatars.githubusercontent.com/u/6602520?v=4?s=64" width="64px;" alt=""/><br /><sub><b>Clonescody</b></sub></a><br /><a href="https://github.com/Zapper-fi/studio/commits?author=Clonescody" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://anson-cheung.com/"><img src="https://avatars.githubusercontent.com/u/12746683?v=4?s=64" width="64px;" alt=""/><br /><sub><b>Emerald</b></sub></a><br /><a href="https://github.com/Zapper-fi/studio/commits?author=the-emerald" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/evLorne"><img src="https://avatars.githubusercontent.com/u/101081187?v=4?s=64" width="64px;" alt=""/><br /><sub><b>EvLorne</b></sub></a><br /><a href="https://github.com/Zapper-fi/studio/commits?author=evLorne" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/0xKratos"><img src="https://avatars.githubusercontent.com/u/32628639?v=4?s=64" width="64px;" alt=""/><br /><sub><b>Kratos</b></sub></a><br /><a href="https://github.com/Zapper-fi/studio/commits?author=0xKratos" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/reganwrench"><img src="https://avatars.githubusercontent.com/u/98139806?v=4?s=64" width="64px;" alt=""/><br /><sub><b>reganwrench</b></sub></a><br /><a href="https://github.com/Zapper-fi/studio/commits?author=reganwrench" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/scruffy-dev"><img src="https://avatars.githubusercontent.com/u/82269917?v=4?s=64" width="64px;" alt=""/><br /><sub><b>scruffy-dev</b></sub></a><br /><a href="https://github.com/Zapper-fi/studio/commits?author=scruffy-dev" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Emile-Filteau"><img src="https://avatars.githubusercontent.com/u/1054341?v=4?s=64" width="64px;" alt=""/><br /><sub><b>Émile Filteau-Tessier</b></sub></a><br /><a href="https://github.com/Zapper-fi/studio/commits?author=Emile-Filteau" title="Code">💻</a> <a href="#question-Emile-Filteau" title="Answering Questions">💬</a> <a href="#maintenance-Emile-Filteau" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/SamIam-0x"><img src="https://avatars.githubusercontent.com/u/43358952?v=4?s=64" width="64px;" alt=""/><br /><sub><b>Sam &#124; Zapper</b></sub></a><br /><a href="https://github.com/Zapper-fi/studio/commits?author=SamIam-0x" title="Documentation">📖</a> <a href="#question-SamIam-0x" title="Answering Questions">💬</a></td>
</tr>
<tr>
<td align="center"><a href="https://www.singlefinance.io/"><img src="https://avatars.githubusercontent.com/u/92788245?v=4?s=64" width="64px;" alt=""/><br /><sub><b>Single Finance Lab</b></sub></a><br /><a href="https://github.com/Zapper-fi/studio/commits?author=singlefinance" title="Code">💻</a></td>
</tr>
</table>

Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "@zapper-fi/studio",
"version": "0.76.1",
"version": "0.101.0",
"description": "Community build apps for Zapper.fi",
"license": "MIT",
"main": "./index.js",
Expand Down
27 changes: 25 additions & 2 deletions scripts/compile-app-assets.js
Expand Up @@ -8,12 +8,12 @@ const exec = util.promisify(require('child_process').exec);

const [targetDirectory] = process.argv.slice(2);

const run = async () => {
const compileLegacyAppLogoImages = async () => {
const { stdout } = await exec(
`git diff HEAD~1 --name-only --diff-filter=AMR | grep "src/apps/.*/assets/logo.png" || true`,
);

if (stdout === '') exit(0);
if (stdout === '') return;

const filepaths = stdout.split('\n').filter(s => s !== '');

Expand All @@ -24,7 +24,30 @@ const run = async () => {
if (!fs.existsSync(targetDirectory)) fs.mkdirSync(targetDirectory, { recursive: true });
fs.copyFileSync(filepath, path.join(targetDirectory, newFile));
});
};

const compileAppAssetImages = async () => {
const { stdout } = await exec(
`git diff HEAD~1 --name-only --diff-filter=AMR | grep "src/apps/.*/assets/.*.png" || true`,
);

if (stdout === '') return;

const filepaths = stdout.split('\n').filter(s => s !== '');

filepaths.forEach(filepath => {
const [, appId] = filepath.match(/src\/apps\/(.*)\/assets\/.*/);
const appDirectory = path.join(targetDirectory, appId);
const newFile = path.basename(filepath);

if (!fs.existsSync(appDirectory)) fs.mkdirSync(appDirectory, { recursive: true });
fs.copyFileSync(filepath, path.join(appDirectory, newFile));
});
};

const run = async () => {
await compileLegacyAppLogoImages();
await compileAppAssetImages();
exit(0);
};

Expand Down
6 changes: 6 additions & 0 deletions src/app-toolkit/app-toolkit.interface.ts
Expand Up @@ -2,6 +2,7 @@ import { StaticJsonRpcProvider } from '@ethersproject/providers';
import { BigNumber as BigNumberJS } from 'bignumber.js';
import { ethers } from 'ethers';

import { AppDefinition } from '~app/app.definition';
import { IContractFactory } from '~contract/contracts';
import { EthersMulticall } from '~multicall';
import { DefaultDataProps } from '~position/display.interface';
Expand All @@ -15,6 +16,11 @@ import { AppToolkitHelperRegistry } from './app-toolkit.helpers';
export const APP_TOOLKIT = Symbol('APP_TOOLKIT');

export interface IAppToolkit {
// Apps
getApps(): Promise<AppDefinition[]>;

getApp(appId: string): Promise<AppDefinition | undefined>;

// Network Related
get globalContracts(): IContractFactory;

Expand Down
3 changes: 2 additions & 1 deletion src/app-toolkit/app-toolkit.module.ts
@@ -1,5 +1,6 @@
import { Module } from '@nestjs/common';

import { AppModule } from '~app/app.module';
import { MulticallModule } from '~multicall/multicall.module';
import { NetworkProviderModule } from '~network-provider/network-provider.module';
import { PositionModule } from '~position/position.module';
Expand All @@ -10,7 +11,7 @@ import { APP_TOOLKIT } from './app-toolkit.interface';
import { AppToolkit } from './app-toolkit.service';

@Module({
imports: [NetworkProviderModule, TokenModule, PositionModule, MulticallModule],
imports: [NetworkProviderModule, TokenModule, PositionModule, MulticallModule, AppModule],
providers: [{ provide: APP_TOOLKIT, useClass: AppToolkit }, AppToolkitHelperRegistry, ...AppToolkitHelpers],
exports: [APP_TOOLKIT, ...AppToolkitHelpers],
})
Expand Down
12 changes: 12 additions & 0 deletions src/app-toolkit/app-toolkit.service.ts
Expand Up @@ -3,6 +3,7 @@ import { BigNumber as BigNumberJS } from 'bignumber.js';
import { Cache } from 'cache-manager';
import { ethers } from 'ethers';

import { AppService } from '~app/app.service';
import { ContractFactory } from '~contract';
import { MulticallService } from '~multicall/multicall.service';
import { NetworkProviderService } from '~network-provider/network-provider.service';
Expand All @@ -20,6 +21,7 @@ export class AppToolkit implements IAppToolkit {
constructor(
// We need the forward ref here, since there is a circular dependency on the AppToolkit, since each helper needs the toolkit
@Inject(forwardRef(() => AppToolkitHelperRegistry)) private readonly helperRegistry: AppToolkitHelperRegistry,
@Inject(AppService) private readonly appService: AppService,
@Inject(NetworkProviderService) private readonly networkProviderService: NetworkProviderService,
@Inject(PositionService) private readonly positionService: PositionService,
@Inject(TokenService) private readonly tokenService: TokenService,
Expand All @@ -29,6 +31,16 @@ export class AppToolkit implements IAppToolkit {
this.contractFactory = new ContractFactory((network: Network) => this.networkProviderService.getProvider(network));
}

// Apps

async getApps() {
return this.appService.getApps();
}

async getApp(appId: string) {
return this.appService.getApp(appId);
}

// Network Related

get globalContracts() {
Expand Down
Expand Up @@ -144,7 +144,7 @@ export class MasterChefContractPositionHelper {
.wrap(this.appToolkit.globalContracts.erc20({ network, address: depositTokenAddress }))
.balanceOf(address),
resolveAddress = async ({ contract }) => (contract as unknown as Contract).address,
resolveLabel = ({ stakedToken }) => `Staked ${getLabelFromToken(stakedToken)}`,
resolveLabel = ({ stakedToken }) => `${getLabelFromToken(stakedToken)}`,
}: MasterChefContractPositionHelperParams<T>): Promise<ContractPosition<MasterChefContractPositionDataProps>[]> {
const provider = this.appToolkit.getNetworkProvider(network);
const multicall = this.appToolkit.getMulticall(network);
Expand Down Expand Up @@ -282,7 +282,7 @@ export class MasterChefContractPositionHelper {
const secondaryLabel = buildDollarDisplayItem(stakedToken.price);
const images = getImagesFromToken(stakedToken);
const statsItems = [
{ label: 'APY', value: buildPercentageDisplayItem(yearlyROI) },
{ label: 'APR', value: buildPercentageDisplayItem(yearlyROI * 100) },
{ label: 'Liquidity', value: buildDollarDisplayItem(liquidity) },
];
const displayProps = {
Expand Down
Expand Up @@ -203,7 +203,7 @@ export class SingleStakingFarmContractPositionHelper {
const secondaryLabel = buildDollarDisplayItem(stakedToken.price);
const images = [getTokenImg(stakedToken.address, network)];
const statsItems = [
{ label: 'APY', value: buildPercentageDisplayItem(rois.yearlyROI * 100) },
{ label: 'APR', value: buildPercentageDisplayItem(rois.yearlyROI * 100) },
{ label: 'Liquidity', value: buildDollarDisplayItem(liquidity) },
];
const displayProps = { label, secondaryLabel, images, statsItems };
Expand Down
55 changes: 55 additions & 0 deletions src/app-toolkit/helpers/position/vault.token-helper.ts
Expand Up @@ -23,37 +23,92 @@ export type VaultTokenDataProps = ExchangeableAppTokenDataProps & {
};

export type VaultTokenHelperParams<T> = {
/**
* Network enum for a given vault
*/
network: Network;
/**
* The application id value should match up to the folder name of a given app
*/
appId: string;
/**
* The group id that is defined for a given app. The value should be obtainable within
* an app's definition file under the groups key.
*/
groupId: string;
/**
* If the vault is dependant on other apps for proper function, then a valid
* application definition must be passed in.
*/
dependencies?: AppGroupsDefinition[];
/**
* Is this token exchangeable?
*/
exchangeable?: boolean;
/**
* The contract factory which will be leveraged during the entire token retrieval process.
* Usually, you can use the application specific generated contract factory. The factory
* is normally stored within an app folder under the `contracts/` sub-folder
*/
resolveContract: (opts: { address: string; network: Network }) => T;
/**
* The address of a vault we wish to retrieve our tokens from.
* You can either use static string addresses, leverage the multicall function (which should map to the
* the contract passed in via resolveContract) or other methods (such as an external API call).
*/
resolveVaultAddresses: (opts: { multicall: EthersMulticall; network: Network }) => string[] | Promise<string[]>;
/**
* The address of an underlying token which correponds to a vault deposit.
* You can either use static string addresses, leverage the multicall function (which should map to the
* the contract passed in via resolveContract) or other methods (such as an external API call).
*/
resolveUnderlyingTokenAddress: (opts: { multicall: EthersMulticall; contract: T }) => string | Promise<string | null>;
/**
* How do we resolve the reserve (aka: the liquidity or total supply) of a given underlying token.
*/
resolveReserve: (opts: {
address: string;
contract: T;
multicall: EthersMulticall;
underlyingToken: Token;
network: Network;
}) => number | Promise<number>;
/**
* How do we resolve the price of a given share of an underlying token.
*/
resolvePricePerShare: (opts: {
contract: T;
multicall: EthersMulticall;
underlyingToken: Token;
reserve: number;
supply: number;
}) => number | Promise<number>;
/**
* How to retrieve the APY of a given vault.
* The APY MUST be a value between 1 - 100 and NOT a fractional value.
* e.g: A value of 6 corresponds to 6%, 42.56 would correspond to 42.56%.
* If empty, we default to 0
*/
resolveApy?: (opts: { vaultAddress: string; multicall: EthersMulticall; contract: T }) => Promise<number>;
/**
* How do we resolve the label that will be displayed on the frontend.
* By default, we will use the symbol.
*/
resolvePrimaryLabel?: (opts: { symbol: string; vaultAddress: string; underlyingToken: Token }) => string;
/**
* How do we resolve the images that will be displayed on the frontend.
* By default, we will attempt to use the underlying token's image.
*/
resolveImages?: (opts: { underlyingToken: Token }) => string[];
};

@Injectable()
export class VaultTokenHelper {
constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {}

/**
* Retrieve all tokens within a given vault.
*/
async getTokens<T>({
network,
appId,
Expand Down
8 changes: 6 additions & 2 deletions src/app-toolkit/helpers/presentation/image.present.ts
Expand Up @@ -6,8 +6,12 @@ export const getTokenImg = (address: string, network: Network = Network.ETHEREUM
return `https://storage.googleapis.com/zapper-fi-assets/tokens/${network}/${address}.png`;
};

export const getAppImg = (appName: string) => {
return `https://storage.googleapis.com/zapper-fi-assets/apps/${appName}.png`;
export const getAppImg = (appId: string) => {
return `https://storage.googleapis.com/zapper-fi-assets/apps/${appId}.png`;
};

export const getAppAssetImage = (appId: string, filename: string) => {
return `https://storage.googleapis.com/zapper-fi-assets/apps/${appId}/${filename}.png`;
};

export const getNetworkImg = (network: Network) => {
Expand Down

0 comments on commit 04182b1

Please sign in to comment.