-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: protocol plugins & manager (#138)
- Integration tests for protocol plugin data - Integration test workflow (Ci) - Unit tests for protocol plugins & BaseProtocolPlugin class - Unit tests for ProtocolManager
- Loading branch information
Showing
37 changed files
with
1,168 additions
and
339 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
name: CI | ||
on: | ||
pull_request: | ||
types: [opened, synchronize] | ||
|
||
jobs: | ||
build: | ||
name: Build and Integration Test | ||
timeout-minutes: 15 | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Check out code | ||
uses: actions/checkout@v3 | ||
with: | ||
fetch-depth: 2 | ||
|
||
- name: Cache turbo build setup | ||
uses: actions/cache@v3 | ||
with: | ||
path: .turbo | ||
key: ${{ runner.os }}-turbo-${{ github.sha }} | ||
restore-keys: | | ||
${{ runner.os }}-turbo- | ||
- uses: pnpm/action-setup@v2.0.1 | ||
with: | ||
version: 8.14.1 | ||
|
||
- name: Setup Node.js environment | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: 20 | ||
cache: 'pnpm' | ||
|
||
- name: Install dependencies | ||
run: pnpm install | ||
|
||
- name: Prebuild | ||
run: pnpm prebuild | ||
|
||
- name: Build | ||
run: pnpm build | ||
|
||
- name: Test | ||
run: pnpm test:integration | ||
env: | ||
ONE_INCH_API_KEY: ${{ secrets.ONE_INCH_API_KEY }} | ||
ONE_INCH_API_VERSION: ${{ secrets.ONE_INCH_API_VERSION }} | ||
ONE_INCH_API_URL: ${{ secrets.ONE_INCH_API_URL }} | ||
ONE_INCH_ALLOWED_SWAP_PROTOCOLS: ${{ secrets.ONE_INCH_ALLOWED_SWAP_PROTOCOLS }} | ||
ONE_INCH_SWAP_CHAIN_IDS: ${{ secrets.ONE_INCH_SWAP_CHAIN_IDS }} | ||
MAINNET_RPC_URL: ${{ secrets.MAINNET_RPC_URL }} |
4 changes: 2 additions & 2 deletions
4
.github/workflows/pull-request-build.yaml → .github/workflows/build-unit-test.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
144 changes: 144 additions & 0 deletions
144
sdk/protocol-manager-service/tests/ProtocolManager.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import { IProtocolManager, IProtocolManagerContext } from '@summerfi/protocol-manager-common' | ||
import { | ||
IProtocolPluginsRegistry, | ||
IProtocolPlugin, | ||
IProtocolPluginContext, | ||
} from '@summerfi/protocol-plugins-common' | ||
import { ProtocolName } from '@summerfi/sdk-common/protocols' | ||
import { ChainInfo } from '@summerfi/sdk-common/common' | ||
import { createPublicClient, http, PublicClient } from 'viem' | ||
import { mainnet } from 'viem/chains' | ||
import { ProtocolManager } from '../src' | ||
import { | ||
TokenService, | ||
PriceService, | ||
ProtocolPluginsRegistry, | ||
} from '@summerfi/protocol-plugins/implementation' | ||
|
||
describe('Protocol Manager', () => { | ||
let ctx: IProtocolManagerContext | ||
let pluginsRegistry: IProtocolPluginsRegistry | ||
let protocolManager: IProtocolManager | ||
let mockPlugins: Partial<Record<ProtocolName, ProtocolPluginConstructor>> | ||
|
||
beforeEach(async () => { | ||
ctx = await createProtocolManagerContext() | ||
mockPlugins = { | ||
[ProtocolName.Spark]: MockPlugin as unknown as ProtocolPluginConstructor, | ||
[ProtocolName.Maker]: MockPlugin as unknown as ProtocolPluginConstructor, | ||
} | ||
pluginsRegistry = new ProtocolPluginsRegistry({ | ||
plugins: mockPlugins, | ||
context: ctx, | ||
}) | ||
protocolManager = new ProtocolManager({ pluginsRegistry }) | ||
}) | ||
|
||
it('should throw an error when getPool is called with an unsupported protocol', async () => { | ||
await expect( | ||
protocolManager.getPool({ protocol: { name: 'unsupportedProtocol' } } as any), | ||
).rejects.toThrow('Invalid pool ID: {"protocol":{"name":"unsupportedProtocol"}}') | ||
}) | ||
|
||
it('should throw an error when getPool is called for a chain that is not supported by the plugin', async () => { | ||
const unsupportedChainId = 'unsupportedChain' | ||
ctx.provider.getChainId = jest.fn().mockResolvedValue(unsupportedChainId) | ||
await expect( | ||
protocolManager.getPool({ protocol: { name: ProtocolName.Spark } } as any), | ||
).rejects.toThrow(`Invalid pool ID: {"protocol":{"name":"Spark"}}`) | ||
}) | ||
|
||
it('should retrieve the pool using the correct plugin and chain ID', async () => { | ||
const ctx = await createProtocolManagerContext() | ||
|
||
class TestMockPlugin extends MockPlugin { | ||
constructor(params: { | ||
protocolName: ProtocolName | ||
context: IProtocolPluginContext | ||
__overrides?: { schema?: any; supportedChains?: any[] } | ||
}) { | ||
super(params) | ||
this.protocolName = ProtocolName.Spark | ||
this.getPool = jest.fn().mockResolvedValue('mockPoolData') | ||
} | ||
} | ||
|
||
const mockPlugins = { | ||
[ProtocolName.Spark]: TestMockPlugin as unknown as ProtocolPluginConstructor, | ||
} | ||
|
||
const pluginsRegistry = new ProtocolPluginsRegistry({ | ||
plugins: mockPlugins, | ||
context: ctx, | ||
}) | ||
|
||
protocolManager = new ProtocolManager({ pluginsRegistry }) | ||
|
||
const chainId = 'supportedChain' | ||
const poolId = { | ||
protocol: { | ||
name: ProtocolName.Spark, | ||
chainInfo: ChainInfo.createFrom({ chainId: 1, name: 'Ethereum' }), | ||
}, | ||
} | ||
|
||
ctx.provider.getChainId = jest.fn().mockResolvedValue(chainId) | ||
|
||
const pool = await protocolManager.getPool(poolId as any) | ||
expect(pool).toBe('mockPoolData') | ||
}) | ||
|
||
it('should throw an error when getPosition is called as it is not implemented', () => { | ||
expect(() => protocolManager.getPosition()).toThrow('Not implemented') | ||
}) | ||
}) | ||
|
||
export type ProtocolPluginConstructor = new (params: { | ||
context: IProtocolPluginContext | ||
}) => IProtocolPlugin | ||
|
||
class MockPlugin implements IProtocolPlugin { | ||
protocolName: ProtocolName | ||
schema: any | ||
supportedChains: any[] | ||
stepBuilders: object | ||
readonly context: IProtocolPluginContext | ||
|
||
constructor(params: { | ||
protocolName: ProtocolName | ||
context: IProtocolPluginContext | ||
__overrides?: { schema?: any; supportedChains?: any[] } | ||
}) { | ||
this.protocolName = params.protocolName | ||
this.context = params.context | ||
this.schema = params.__overrides?.schema ?? {} | ||
this.supportedChains = params.__overrides?.supportedChains ?? [] | ||
this.stepBuilders = {} | ||
} | ||
|
||
getPool = jest.fn() | ||
getPosition = jest.fn() | ||
// @ts-ignore | ||
isPoolId = jest.fn() | ||
validatePoolId = jest.fn() | ||
getActionBuilder = jest.fn() | ||
ctx = () => this.context | ||
} | ||
|
||
async function createProtocolManagerContext(): Promise<IProtocolManagerContext> { | ||
const RPC_URL = process.env['MAINNET_RPC_URL'] || '' | ||
const provider: PublicClient = createPublicClient({ | ||
batch: { | ||
multicall: true, | ||
}, | ||
chain: mainnet, | ||
transport: http(RPC_URL), | ||
}) | ||
|
||
return { | ||
provider, | ||
tokenService: new TokenService(), | ||
priceService: new PriceService(provider), | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 1 addition & 2 deletions
3
sdk/protocol-plugins-common/src/interfaces/IProtocolPluginContext.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,10 @@ | ||
import { PublicClient } from 'viem' | ||
import { IPriceService } from './IPriceService' | ||
import { ITokenService } from './ITokenService' | ||
import { IContractProvider } from './IContractProvider' | ||
// import { IContractProvider } from './IContractProvider' | ||
|
||
export interface IProtocolPluginContext { | ||
provider: PublicClient | ||
tokenService: ITokenService | ||
priceService: IPriceService | ||
contractProvider: IContractProvider | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.