Skip to content

Commit 5f82512

Browse files
committed
feat: add neptune and swell
1 parent a894323 commit 5f82512

File tree

3 files changed

+164
-0
lines changed

3 files changed

+164
-0
lines changed

src/swapService/config/swell.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { type ChainRoutingConfig, SwapperMode } from "../interface"
2+
import { StrategyBalmySDK, StrategyRepayWrapper } from "../strategies"
3+
4+
const swellRoutingConfig: ChainRoutingConfig = [
5+
// WRAPPERS
6+
{
7+
strategy: StrategyRepayWrapper.name(),
8+
match: {
9+
isRepay: true,
10+
swapperModes: [SwapperMode.EXACT_IN],
11+
},
12+
},
13+
// DEFAULTS
14+
{
15+
strategy: StrategyBalmySDK.name(),
16+
config: {
17+
sourcesFilter: {
18+
includeSources: ["neptune", "li-fi"],
19+
},
20+
},
21+
match: {},
22+
},
23+
]
24+
25+
export default swellRoutingConfig

src/swapService/strategies/balmySDK/customSourceList.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import type { IFetchService, IProviderService } from "@balmy/sdk"
22
import { LocalSourceList } from "@balmy/sdk/dist/services/quotes/source-lists/local-source-list"
33
import { CustomLiFiQuoteSource } from "./lifiQuoteSource"
4+
import { CustomNeptuneQuoteSource } from "./neptuneQuoteSource"
45
import { CustomOneInchQuoteSource } from "./oneInchQuoteSource"
56
import { CustomOpenOceanQuoteSource } from "./openOceanQuoteSource"
67
import { CustomPendleQuoteSource } from "./pendleQuoteSource"
8+
79
type ConstructorParameters = {
810
providerService: IProviderService
911
fetchService: IFetchService
@@ -14,6 +16,7 @@ const customSources = {
1416
"li-fi": new CustomLiFiQuoteSource(),
1517
pendle: new CustomPendleQuoteSource(),
1618
"open-ocean": new CustomOpenOceanQuoteSource(),
19+
neptune: new CustomNeptuneQuoteSource(),
1720
}
1821
export class CustomSourceList extends LocalSourceList {
1922
constructor({ providerService, fetchService }: ConstructorParameters) {
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import type {
2+
BuildTxParams,
3+
IQuoteSource,
4+
QuoteParams,
5+
QuoteSourceMetadata,
6+
SourceQuoteResponse,
7+
SourceQuoteTransaction,
8+
} from "@balmy/sdk/dist/services/quotes/quote-sources/types"
9+
import {
10+
addQuoteSlippage,
11+
calculateAllowanceTarget,
12+
failed,
13+
} from "@balmy/sdk/dist/services/quotes/quote-sources/utils"
14+
import qs from "qs"
15+
16+
// Supported networks: https://docs.1inch.io/docs/aggregation-protocol/introduction/#supported-networkschains
17+
export const NEPTUNE_METADATA: QuoteSourceMetadata<NeptuneSupport> = {
18+
name: "Swell",
19+
supports: {
20+
chains: [1923],
21+
swapAndTransfer: true,
22+
buyOrders: false,
23+
},
24+
logoURI: "ipfs://QmNr5MnyZKUv7rMhMyZPbxPbtc1A1yAVAqEEgVbep1hdBx",
25+
}
26+
const chainNames: Record<number, string> = {
27+
1923: "swell",
28+
}
29+
type NeptuneSupport = { buyOrders: false; swapAndTransfer: true }
30+
type NeptuneConfig = object
31+
type NeptuneData = { tx: SourceQuoteTransaction }
32+
export class CustomNeptuneQuoteSource
33+
implements IQuoteSource<NeptuneSupport, NeptuneConfig, NeptuneData>
34+
{
35+
getMetadata() {
36+
return NEPTUNE_METADATA
37+
}
38+
39+
async quote(
40+
params: QuoteParams<NeptuneSupport, NeptuneConfig>,
41+
): Promise<SourceQuoteResponse<NeptuneData>> {
42+
const { amountOut, to, data } = await this.getQuote(params)
43+
44+
const quote = {
45+
sellAmount: params.request.order.sellAmount,
46+
buyAmount: BigInt(amountOut),
47+
estimatedGas: undefined,
48+
allowanceTarget: calculateAllowanceTarget(params.request.sellToken, to),
49+
customData: {
50+
tx: {
51+
to,
52+
calldata: data,
53+
value: 0n,
54+
},
55+
},
56+
}
57+
58+
return addQuoteSlippage(
59+
quote,
60+
params.request.order.type,
61+
params.request.config.slippagePercentage,
62+
)
63+
}
64+
65+
async buildTx({
66+
request,
67+
}: BuildTxParams<
68+
NeptuneConfig,
69+
NeptuneData
70+
>): Promise<SourceQuoteTransaction> {
71+
return request.customData.tx
72+
}
73+
74+
private async getQuote({
75+
components: { fetchService },
76+
request: {
77+
chainId,
78+
sellToken,
79+
buyToken,
80+
order,
81+
config: { slippagePercentage, timeout },
82+
accounts: { takeFrom, recipient },
83+
},
84+
}: QuoteParams<NeptuneSupport, NeptuneConfig>) {
85+
const queryParams = {
86+
tokenIn: sellToken,
87+
tokenOut: buyToken,
88+
amountIn: order.sellAmount.toString(),
89+
receiver: recipient ?? takeFrom,
90+
slippage: String(slippagePercentage / 100), // 1 = 100%
91+
}
92+
const queryString = qs.stringify(queryParams, {
93+
skipNulls: true,
94+
arrayFormat: "comma",
95+
})
96+
const url = `https://agg-api.nep.finance/v1/${chainNames[chainId]}/swap?${queryString}`
97+
const response = await fetchService.fetch(url, {
98+
timeout,
99+
headers: getHeaders(),
100+
})
101+
if (!response.ok) {
102+
failed(
103+
NEPTUNE_METADATA,
104+
chainId,
105+
sellToken,
106+
buyToken,
107+
(await response.text()) || `Failed with status ${response.status}`,
108+
)
109+
}
110+
const {
111+
amountOut,
112+
tx: { router, data },
113+
} = await response.json()
114+
return { amountOut, data, to: router }
115+
}
116+
117+
isConfigAndContextValidForQuoting(
118+
config: Partial<NeptuneConfig> | undefined,
119+
): config is NeptuneConfig {
120+
return true
121+
}
122+
123+
isConfigAndContextValidForTxBuilding(
124+
config: Partial<NeptuneConfig> | undefined,
125+
): config is NeptuneConfig {
126+
return true
127+
}
128+
}
129+
130+
function getHeaders() {
131+
const headers: Record<string, string> = {
132+
accept: "application/json",
133+
}
134+
135+
return headers
136+
}

0 commit comments

Comments
 (0)