Skip to content

Commit 7454f67

Browse files
committed
add magpie api key
1 parent cdd7782 commit 7454f67

13 files changed

+189
-14
lines changed

.env.template

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ OKX_SECRET_KEY=""
4242
ODOS_API_KEY=""
4343
ODOS_REFERRAL_CODE=""
4444
OOGABOOGA_API_KEY=""
45-
OX_API_KEY=""
45+
OX_API_KEY=""
46+
MAGPIE_API_KEY=""

src/swapService/strategies/balmySDK/customSourceList.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import type { IFetchService, IProviderService } from "@balmy/sdk"
22
import { LocalSourceList } from "@balmy/sdk/dist/services/quotes/source-lists/local-source-list"
3-
import { CustomLiFiQuoteSource } from "./lifiQuoteSource"
4-
import { CustomNeptuneQuoteSource } from "./neptuneQuoteSource"
5-
import { CustomOdosQuoteSource } from "./odosQuoteSource"
6-
import { CustomOkuQuoteSource } from "./okuQuoteSource"
7-
import { CustomOneInchQuoteSource } from "./oneInchQuoteSource"
8-
import { CustomOogaboogaQuoteSource } from "./oogaboogaQuoteSource"
9-
import { CustomOpenOceanQuoteSource } from "./openOceanQuoteSource"
10-
import { CustomPendleQuoteSource } from "./pendleQuoteSource"
11-
import { CustomUniswapQuoteSource } from "./uniswapQuoteSource"
3+
import { CustomLiFiQuoteSource } from "./sources/lifiQuoteSource"
4+
import { CustomMagpieQuoteSource } from "./sources/magpieQuoteSource"
5+
import { CustomNeptuneQuoteSource } from "./sources/neptuneQuoteSource"
6+
import { CustomOdosQuoteSource } from "./sources/odosQuoteSource"
7+
import { CustomOkuQuoteSource } from "./sources/okuQuoteSource"
8+
import { CustomOneInchQuoteSource } from "./sources/oneInchQuoteSource"
9+
import { CustomOogaboogaQuoteSource } from "./sources/oogaboogaQuoteSource"
10+
import { CustomOpenOceanQuoteSource } from "./sources/openOceanQuoteSource"
11+
import { CustomPendleQuoteSource } from "./sources/pendleQuoteSource"
12+
import { CustomUniswapQuoteSource } from "./sources/uniswapQuoteSource"
1213

1314
type ConstructorParameters = {
1415
providerService: IProviderService
@@ -24,6 +25,7 @@ const customSources = {
2425
odos: new CustomOdosQuoteSource(),
2526
oogabooga: new CustomOogaboogaQuoteSource(),
2627
uniswap: new CustomUniswapQuoteSource(),
28+
magpie: new CustomMagpieQuoteSource(),
2729
oku_bob_icecreamswap: new CustomOkuQuoteSource(
2830
"icecreamswap",
2931
"IceCreamSwap",
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import {
2+
Addresses,
3+
type ChainId,
4+
Chains,
5+
type TokenAddress,
6+
isSameAddress,
7+
} from "@balmy/sdk"
8+
import { AlwaysValidConfigAndContextSource } from "@balmy/sdk/dist/services/quotes/quote-sources/base/always-valid-source"
9+
import type {
10+
BuildTxParams,
11+
QuoteParams,
12+
QuoteSourceMetadata,
13+
SourceQuoteResponse,
14+
} from "@balmy/sdk/dist/services/quotes/quote-sources/types"
15+
import {
16+
addQuoteSlippage,
17+
calculateAllowanceTarget,
18+
failed,
19+
} from "@balmy/sdk/dist/services/quotes/quote-sources/utils"
20+
import qs from "qs"
21+
import { parseUnits } from "viem"
22+
23+
const SUPPORTED_CHAINS: Record<ChainId, string> = {
24+
[Chains.ARBITRUM.chainId]: "arbitrum",
25+
[Chains.AVALANCHE.chainId]: "avalanche",
26+
[Chains.BNB_CHAIN.chainId]: "bsc",
27+
[Chains.ETHEREUM.chainId]: "ethereum",
28+
[Chains.POLYGON.chainId]: "polygon",
29+
[Chains.OPTIMISM.chainId]: "optimism",
30+
[Chains.BASE.chainId]: "base",
31+
[Chains.POLYGON_ZKEVM.chainId]: "polygonzk",
32+
[Chains.BLAST.chainId]: "blast",
33+
[Chains.SCROLL.chainId]: "scroll",
34+
[Chains.METIS_ANDROMEDA.chainId]: "metis",
35+
[Chains.FANTOM.chainId]: "fantom",
36+
[Chains.SONIC.chainId]: "sonic",
37+
}
38+
39+
const MAGPIE_METADATA: QuoteSourceMetadata<MagpieSupport> = {
40+
name: "Magpie",
41+
supports: {
42+
chains: Object.keys(SUPPORTED_CHAINS).map(Number),
43+
swapAndTransfer: true,
44+
buyOrders: false,
45+
},
46+
logoURI: "ipfs://QmfR2ybY1gvctAxU5KArQ1UDXFixBY8ehgTBUBvUqY4Q4b",
47+
}
48+
type MagpieSupport = { buyOrders: false; swapAndTransfer: true }
49+
type MagpieConfig = { sourceAllowlist?: string[]; apiKey?: string }
50+
type MagpieData = { quoteId: string }
51+
export class CustomMagpieQuoteSource extends AlwaysValidConfigAndContextSource<
52+
MagpieSupport,
53+
MagpieConfig,
54+
MagpieData
55+
> {
56+
getMetadata() {
57+
return MAGPIE_METADATA
58+
}
59+
60+
async quote({
61+
components: { fetchService },
62+
request: {
63+
chainId,
64+
sellToken,
65+
buyToken,
66+
order,
67+
accounts: { takeFrom, recipient },
68+
config: { slippagePercentage, timeout },
69+
},
70+
config,
71+
}: QuoteParams<MagpieSupport, MagpieConfig>): Promise<
72+
SourceQuoteResponse<MagpieData>
73+
> {
74+
const quoteQueryParams = {
75+
network: SUPPORTED_CHAINS[chainId],
76+
fromTokenAddress: mapToken(sellToken),
77+
toTokenAddress: mapToken(buyToken),
78+
sellAmount: order.sellAmount.toString(),
79+
slippage: slippagePercentage / 100,
80+
liquiditySources: config.sourceAllowlist,
81+
fromAddress: takeFrom,
82+
toAddress: recipient ?? takeFrom,
83+
gasless: false,
84+
}
85+
86+
const quoteQueryString = qs.stringify(quoteQueryParams, {
87+
skipNulls: true,
88+
arrayFormat: "comma",
89+
})
90+
const quoteUrl = `https://api.magpiefi.xyz/aggregator/quote?${quoteQueryString}`
91+
const headers: Record<string, string> = {}
92+
if (config.apiKey) {
93+
headers["apikey"] = config.apiKey
94+
}
95+
const quoteResponse = await fetchService.fetch(quoteUrl, {
96+
timeout,
97+
headers,
98+
})
99+
if (!quoteResponse.ok) {
100+
failed(
101+
MAGPIE_METADATA,
102+
chainId,
103+
sellToken,
104+
buyToken,
105+
await quoteResponse.text(),
106+
)
107+
}
108+
const {
109+
id: quoteId,
110+
amountOut,
111+
targetAddress,
112+
fees,
113+
} = await quoteResponse.json()
114+
const estimatedGasNum: `${number}` | undefined = fees.find(
115+
(fee: { type: string; value: `${number}` }) => fee.type === "gas",
116+
)?.value
117+
const estimatedGas = estimatedGasNum
118+
? parseUnits(estimatedGasNum, 9)
119+
: undefined
120+
121+
const quote = {
122+
sellAmount: order.sellAmount,
123+
buyAmount: BigInt(amountOut),
124+
estimatedGas,
125+
allowanceTarget: calculateAllowanceTarget(sellToken, targetAddress),
126+
customData: { quoteId, takeFrom, recipient },
127+
}
128+
129+
return addQuoteSlippage(quote, order.type, slippagePercentage)
130+
}
131+
132+
async buildTx({
133+
components: { fetchService },
134+
request: {
135+
chainId,
136+
sellToken,
137+
buyToken,
138+
config: { timeout },
139+
customData: { quoteId },
140+
},
141+
}: BuildTxParams<MagpieConfig, MagpieData>): Promise<SourceQuoteTransaction> {
142+
const transactionQueryParams = {
143+
quoteId,
144+
estimateGas: false,
145+
}
146+
const transactionQueryString = qs.stringify(transactionQueryParams, {
147+
skipNulls: true,
148+
arrayFormat: "comma",
149+
})
150+
const transactionUrl = `https://api.magpiefi.xyz/aggregator/transaction?${transactionQueryString}`
151+
const transactionResponse = await fetchService.fetch(transactionUrl, {
152+
timeout,
153+
})
154+
if (!transactionResponse.ok) {
155+
failed(
156+
MAGPIE_METADATA,
157+
chainId,
158+
sellToken,
159+
buyToken,
160+
await transactionResponse.text(),
161+
)
162+
}
163+
const { to, value, data } = await transactionResponse.json()
164+
return { to, calldata: data, value: BigInt(value) }
165+
}
166+
}
167+
168+
function mapToken(address: TokenAddress) {
169+
return isSameAddress(address, Addresses.NATIVE_TOKEN)
170+
? Addresses.ZERO_ADDRESS
171+
: address
172+
}

src/swapService/strategies/balmySDK/okuQuoteSource.ts renamed to src/swapService/strategies/balmySDK/sources/okuQuoteSource.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@ import {
22
type Address,
33
Addresses,
44
type ChainId,
5-
Chains,
6-
Contract,
75
type GasPrice,
86
type TimeString,
97
type TokenAddress,
10-
calculateDeadline,
118
getChainByKey,
129
isSameAddress,
1310
} from "@balmy/sdk"

0 commit comments

Comments
 (0)