Skip to content

Commit

Permalink
Merge pull request #277 from pecuniafinance/development
Browse files Browse the repository at this point in the history
feat/ Osmosis Chain/Connector
  • Loading branch information
rapcmia committed Mar 15, 2024
2 parents 5015988 + 3db1553 commit 9d36722
Show file tree
Hide file tree
Showing 45 changed files with 19,726 additions and 203 deletions.
270 changes: 230 additions & 40 deletions docs/swagger/definitions.yml

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions package.json
Expand Up @@ -23,9 +23,11 @@
"test:scripts": "jest -i --verbose ./test-scripts/*.test.ts"
},
"dependencies": {
"@cosmjs/amino": "^0.32.2",
"@bancor/carbon-sdk": "^0.0.93-DEV",
"@cosmjs/proto-signing": "^0.31.1",
"@cosmjs/stargate": "^0.31.1",
"@cosmjs/tendermint-rpc": "^0.32.2",
"@crocswap/sdk": "^2.4.5",
"@ethersproject/abstract-provider": "5.7.0",
"@ethersproject/address": "5.7.0",
Expand All @@ -37,6 +39,7 @@
"@harmony-js/utils": "^0.1.56",
"@improbable-eng/grpc-web": "^0.13.0",
"@injectivelabs/sdk-ts": "^1.10.58",
"@osmonauts/math": "^1.11.3",
"@pancakeswap/sdk": "^4.0.0",
"@pancakeswap/smart-router": "^4.2.1",
"@pancakeswap/swap-sdk-core": "^1.0.0",
Expand Down Expand Up @@ -92,6 +95,8 @@
"minimist": "^1.2.6",
"morgan": "^1.10.0",
"near-api-js": "1.0.0",
"osmo-query": "16.5.2",
"osmojs": "16.5.1",
"promise-retry": "^2.0.1",
"quickswap-sdk": "^3.0.8",
"quipuswap-v3-sdk": "^0.0.7",
Expand Down
44 changes: 36 additions & 8 deletions src/amm/amm.controllers.ts
Expand Up @@ -86,12 +86,17 @@ import { Algorand } from '../chains/algorand/algorand';
import { Tinyman } from '../connectors/tinyman/tinyman';
import { Plenty } from '../connectors/plenty/plenty';
import { QuipuSwap } from '../connectors/quipuswap/quipuswap';
import { Osmosis } from '../chains/osmosis/osmosis';
import { Carbonamm } from '../connectors/carbon/carbonAMM';

export async function price(req: PriceRequest): Promise<PriceResponse> {
const chain = await getInitializedChain<
Algorand | Ethereumish | Nearish | Tezosish
Algorand | Ethereumish | Nearish | Tezosish | Osmosis
>(req.chain, req.network);
if (chain instanceof Osmosis){
return chain.controller.price(chain as unknown as Osmosis, req);
}

const connector: Uniswapish | RefAMMish | Tinyman | Plenty | QuipuSwap =
await getConnector<Uniswapish | RefAMMish | Tinyman | Plenty | QuipuSwap>(
req.chain,
Expand All @@ -117,8 +122,12 @@ export async function price(req: PriceRequest): Promise<PriceResponse> {

export async function trade(req: TradeRequest): Promise<TradeResponse> {
const chain = await getInitializedChain<
Algorand | Ethereumish | Nearish | Tezosish
Algorand | Ethereumish | Nearish | Tezosish | Osmosis
>(req.chain, req.network);
if (chain instanceof Osmosis){
return chain.controller.trade(chain as unknown as Osmosis, req);
}

const connector: Uniswapish | RefAMMish | Tinyman | Plenty | QuipuSwap =
await getConnector<Uniswapish | RefAMMish | Tinyman | Plenty | QuipuSwap>(
req.chain,
Expand All @@ -145,7 +154,10 @@ export async function trade(req: TradeRequest): Promise<TradeResponse> {
export async function addLiquidity(
req: AddLiquidityRequest
): Promise<AddLiquidityResponse> {
const chain = await getInitializedChain<Ethereumish>(req.chain, req.network);
const chain = await getInitializedChain<Ethereumish | Osmosis>(req.chain, req.network);
if (chain instanceof Osmosis){
return chain.controller.addLiquidity(chain as unknown as Osmosis, req);
}
const connector: UniswapLPish = await getConnector<UniswapLPish>(
req.chain,
req.network,
Expand All @@ -158,7 +170,10 @@ export async function addLiquidity(
export async function reduceLiquidity(
req: RemoveLiquidityRequest
): Promise<RemoveLiquidityResponse> {
const chain = await getInitializedChain<Ethereumish>(req.chain, req.network);
const chain = await getInitializedChain<Ethereumish | Osmosis>(req.chain, req.network);
if (chain instanceof Osmosis){
return chain.controller.removeLiquidity(chain as unknown as Osmosis, req);
}
const connector: UniswapLPish = await getConnector<UniswapLPish>(
req.chain,
req.network,
Expand All @@ -171,7 +186,10 @@ export async function reduceLiquidity(
export async function collectFees(
req: CollectEarnedFeesRequest
): Promise<RemoveLiquidityResponse> {
const chain = await getInitializedChain<Ethereumish>(req.chain, req.network);
const chain = await getInitializedChain<Ethereumish | Osmosis>(req.chain, req.network);
if (chain instanceof Osmosis){
return chain.controller.collectFees(chain as unknown as Osmosis, req);
}
const connector: UniswapLPish = await getConnector<UniswapLPish>(
req.chain,
req.network,
Expand All @@ -183,7 +201,10 @@ export async function collectFees(
export async function positionInfo(
req: PositionRequest
): Promise<PositionResponse> {
const chain = await getInitializedChain<Ethereumish>(req.chain, req.network);
const chain = await getInitializedChain<Ethereumish | Osmosis>(req.chain, req.network);
if (chain instanceof Osmosis){
return chain.controller.poolPositions(chain as unknown as Osmosis, req);
}
const connector: UniswapLPish = await getConnector<UniswapLPish>(
req.chain,
req.network,
Expand All @@ -195,7 +216,10 @@ export async function positionInfo(
export async function poolPrice(
req: PoolPriceRequest
): Promise<PoolPriceResponse> {
const chain = await getInitializedChain<Ethereumish>(req.chain, req.network);
const chain = await getInitializedChain<Ethereumish | Osmosis>(req.chain, req.network);
if (chain instanceof Osmosis){
return chain.controller.poolPrice(chain as unknown as Osmosis, req);
}
const connector: UniswapLPish = await getConnector<UniswapLPish>(
req.chain,
req.network,
Expand All @@ -208,8 +232,12 @@ export async function estimateGas(
req: NetworkSelectionRequest
): Promise<EstimateGasResponse> {
const chain = await getInitializedChain<
Algorand | Ethereumish | Nearish | Tezosish
Algorand | Ethereumish | Nearish | Tezosish | Osmosis
>(req.chain, req.network);
if (chain instanceof Osmosis){
return chain.controller.estimateGas(chain as unknown as Osmosis);
}

const connector: Uniswapish | RefAMMish | Tinyman | Plenty | QuipuSwap =
await getConnector<Uniswapish | RefAMMish | Plenty | QuipuSwap>(
req.chain,
Expand Down
73 changes: 46 additions & 27 deletions src/amm/amm.requests.ts
@@ -1,3 +1,4 @@
import { CoinAndSymbol, SerializableExtendedPool as CosmosSerializableExtendedPool } from '../chains/osmosis/osmosis.types';
import { PerpPosition } from '../connectors/perp/perp';
import {
NetworkSelectionRequest,
Expand Down Expand Up @@ -29,24 +30,27 @@ export interface PriceResponse {
gasPrice: number;
gasPriceToken: string;
gasLimit: number;
gasCost: string;
gasCost: string; // also gasUsed for Cosmos prices
gasWanted?: string;
}

export interface PoolPriceRequest extends NetworkSelectionRequest {
token0: string;
token1: string;
fee: string;
period: number;
interval: number;
address?: string
fee?: string;
period?: number;
interval?: number;
}

export interface PoolPriceResponse {
token0: string;
token1: string;
fee: string;
period: number;
interval: number;
prices: string[];
fee?: string;
period?: number;
interval?: number;
prices?: string[];
pools?: CosmosSerializableExtendedPool[];
network: string;
timestamp: number;
latency: number;
Expand All @@ -71,32 +75,37 @@ export interface TradeResponse {
latency: number;
base: string;
quote: string;
amount: string;
amount: string; // traderequest.amount
finalAmountReceived?: string; // Cosmos
rawAmount: string;
finalAmountReceived_basetoken?: string; // Cosmos
expectedIn?: string;
expectedOut?: string;
price: string;
expectedOut?: string; // Cosmos: expectedAmountReceived
expectedPrice?: string; // Cosmos
price: string; // Cosmos: finalPrice
gasPrice: number;
gasPriceToken: string;
gasLimit: number;
gasCost: string;
gasWanted?: string; // Cosmos
gasCost: string; // Cosmos: gasUsed
nonce?: number;
txHash: string | any | undefined;
}

export interface AddLiquidityRequest extends NetworkSelectionRequest {
export interface AddLiquidityRequest extends NetworkSelectionRequest { // now also cosmos add swap position OR cosmos add LP position
address: string;
token0: string;
token1: string;
amount0: string;
amount1: string;
fee: string;
lowerPrice: string; // integer as string
upperPrice: string; // integer as string
tokenId?: number;
fee?: string;
lowerPrice?: string; // integer as string // COSMOS - using this != undefined then call addpositionLP(), else: addposition()
upperPrice?: string; // integer as string
tokenId?: number; // COSMOS: poolId - will select one for you if not provided
nonce?: number;
maxFeePerGas?: string;
maxPriorityFeePerGas?: string;
allowedSlippage?: string; // COSMOS: used to calc TokenMinAmount
}

export interface AddLiquidityResponse {
Expand All @@ -106,42 +115,52 @@ export interface AddLiquidityResponse {
token0: string;
token1: string;
fee: string;
tokenId: number;
gasPrice: number;
tokenId: number; // COSMOS - this is poolId
gasPrice: number | string; // COSMOS: string
gasPriceToken: string;
gasLimit: number;
gasCost: string;
gasCost: string; // gasUsed for Cosmos
gasWanted?: string;
nonce: number;
txHash: string | undefined;
poolAddress?: string; // Cosmos only
poolShares?: string; // Cosmos only
token0FinalAmount?: string; // Cosmos only
token1FinalAmount?: string; // Cosmos only
}

export interface CollectEarnedFeesRequest extends NetworkSelectionRequest {
address: string;
tokenId: number;
tokenId: number; // COSMOS - this is poolId
nonce?: number;
maxFeePerGas?: string;
maxPriorityFeePerGas?: string;
}

export interface RemoveLiquidityRequest extends CollectEarnedFeesRequest {
decreasePercent?: number;
allowedSlippage?: string;
}

export interface RemoveLiquidityResponse {
network: string;
timestamp: number;
latency: number;
tokenId: number;
gasPrice: number;
tokenId: number; // COSMOS - this is poolId
gasPrice: number | string; // COSMOS: string
gasPriceToken: string;
gasLimit: number;
gasCost: string;
nonce: number;
gasLimit: number | string;
gasCost: string; // gasUsed for Cosmos
nonce?: number;
txHash: string | undefined;
gasWanted?: string;
balances?: CoinAndSymbol[];
isCollectFees?: boolean;
}

export interface PositionRequest extends NetworkSelectionRequest {
tokenId: number;
tokenId?: number; // COSMOS - this is poolId. requried for both
address?: string; // COSMOS only/required (no idea how this works without address for others)
}

export interface PositionResponse extends LPPositionInfo {
Expand Down
23 changes: 16 additions & 7 deletions src/amm/amm.validators.ts
Expand Up @@ -11,11 +11,16 @@ import {
validateChain,
validateNetwork,
validateNonce,
validateAddress,
validateMaxFeePerGas,
validateMaxPriorityFeePerGas,
isAddress as isEthereumAddress,
invalidAddressError,
} from '../chains/ethereum/ethereum.validators';

import {
isValidCosmosAddress
} from '../chains/cosmos/cosmos.validators';

import { FeeAmount } from '@uniswap/v3-sdk';

export const invalidConnectorError: string =
Expand Down Expand Up @@ -63,6 +68,13 @@ export const validateConnector: Validator = mkValidator(
(val) => typeof val === 'string'
);

// given a request, look for a key called address that is an Ethereum or Cosmos wallet
export const validateAddress: Validator = mkValidator(
'address',
invalidAddressError,
(val) => typeof val === 'string' && (isEthereumAddress(val) || isValidCosmosAddress(val))
);

export const validateQuote: Validator = mkValidator(
'quote',
invalidQuoteError,
Expand Down Expand Up @@ -121,8 +133,7 @@ export const validateFee: Validator = mkValidator(
'fee',
invalidFeeTier,
(val) =>
typeof val === 'string' &&
Object.keys(FeeAmount).includes(val.toUpperCase())
typeof val === 'string' && Object.keys(FeeAmount).includes(val.toUpperCase())
);

export const validateLowerPrice: Validator = mkValidator(
Expand All @@ -149,9 +160,7 @@ export const validateLimitPrice: Validator = mkValidator(
export const validateTokenId: Validator = mkValidator(
'tokenId',
invalidTokenIdError,
(val) =>
typeof val === 'undefined' ||
(typeof val === 'number' && val >= 0 && Number.isInteger(val)),
(val) => typeof val === 'number' && val >= 0 && Number.isInteger(val),
true
);

Expand Down Expand Up @@ -181,7 +190,7 @@ export const validateDecreasePercent: Validator = mkValidator(
export const validateAllowedSlippage: Validator = mkValidator(
'allowedSlippage',
invalidAllowedSlippageError,
(val) => typeof val === 'string' && isFractionString(val),
(val) => typeof val === 'string' && (isFractionString(val) || val.includes('%')),
true
);

Expand Down

0 comments on commit 9d36722

Please sign in to comment.