UNPKG

@brian-ai/ee-portals-solver

Version:

> ⚠️ README: work in progress.

359 lines (350 loc) 10.9 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { PortalsSolver: () => PortalsSolver }); module.exports = __toCommonJS(index_exports); var import_ee_core4 = require("@brian-ai/ee-core"); // src/actions/deposit.ts var import_ky = __toESM(require("ky"), 1); var import_viem = require("viem"); // src/constants.ts var NATIVE_ADDRESS = "0x0000000000000000000000000000000000000000"; // src/utils.ts var ADJUSTED_CHAINS_NAME_PORTALS = { "arbitrum one": "arbitrum", "op mainnet": "optimism", avalanche: "avalanche", "bnb smart chain": "bsc", gnosis: "gnosis", polygon: "polygon", base: "base", ethereum: "ethereum", fantom: "fantom" }; // src/actions/deposit.ts var import_ee_core = require("@brian-ai/ee-core"); var portalsDeposit = async ({ apiUrl: inputApiUrl, apiKey, feeReceiver, fee, slippage, chain, address, inputToken, outputToken, amount }) => { const adjustedChainName = ADJUSTED_CHAINS_NAME_PORTALS[chain.name.toLowerCase()]; const publicClient = (0, import_viem.createPublicClient)({ chain, transport: (0, import_viem.http)() }); const blockNumber = await publicClient.getBlockNumber(); const tokens = `${adjustedChainName.toLowerCase()}:${outputToken}`; const tokenInfoUrl = `${inputApiUrl}/tokens?ids=${tokens}&networks=${adjustedChainName.toLowerCase()}&sortBy=liquidity&sortDirection=desc`; const tokenOut = await fetch(tokenInfoUrl, { headers: { Authorization: `Bearer ${apiKey}` } }); const tokenOutJson = await tokenOut.json(); const tokenOutAddress = tokenOutJson.tokens[0].address; if (!tokenOut) { return Promise.reject("Portals: token not supported"); } const depositUrl = `${inputApiUrl}/portal?sender=${address}&inputToken=${adjustedChainName.toLowerCase()}%3A${inputToken}&inputAmount=${amount}&outputToken=${adjustedChainName.toLowerCase()}%3A${tokenOutAddress}&slippageTolerancePercentage=${slippage}&partner=${feeReceiver}&feePercentage=${fee}&validate=false`; const data = await import_ky.default.get(depositUrl, { headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` } }).json(); const steps = [ { chainId: chain.id, blockNumber: Number(blockNumber), from: data.tx.from, to: data.tx.to, gasLimit: "100000", gasPrice: void 0, data: data.tx.data, value: data.tx.value } ]; if (inputToken !== NATIVE_ADDRESS) { const approveAmount = await (0, import_ee_core.getAmountToApprove)( inputToken, address, data.tx.to, amount, chain ); if (approveAmount > 0n) { steps.unshift({ chainId: chain.id, blockNumber: Number(blockNumber), from: address, to: inputToken, gasLimit: "80000", gasPrice: void 0, data: (0, import_viem.encodeFunctionData)({ abi: import_viem.erc20Abi, functionName: "approve", args: [data.tx.to, approveAmount] }), value: "0" }); } } return steps; }; // src/actions/withdraw.ts var import_ky2 = __toESM(require("ky"), 1); var import_viem2 = require("viem"); var import_ee_core2 = require("@brian-ai/ee-core"); var portalsWithdraw = async ({ apiUrl: inputApiUrl, apiKey, feeReceiver, fee, slippage, chain, address, inputToken, outputToken, amount }) => { const adjustedChainName = ADJUSTED_CHAINS_NAME_PORTALS[chain.name.toLowerCase()]; const publicClient = (0, import_viem2.createPublicClient)({ chain, transport: (0, import_viem2.http)() }); const blockNumber = await publicClient.getBlockNumber(); const tokens = `${adjustedChainName.toLowerCase()}:${outputToken}`; const tokenInfoUrl = `${inputApiUrl}/tokens?ids=${tokens}&networks=${adjustedChainName.toLowerCase()}&sortBy=liquidity&sortDirection=desc`; const tokenOut = await fetch(tokenInfoUrl, { headers: { Authorization: `Bearer ${apiKey}` } }); const tokenOutJson = await tokenOut.json(); const tokenOutAddress = tokenOutJson.tokens[0].address; if (!tokenOut) { return Promise.reject("Portals: token not supported"); } const withdrawUrl = `${inputApiUrl}/portal?sender=${address}&inputToken=${adjustedChainName.toLowerCase()}%3A${inputToken}&inputAmount=${amount}&outputToken=${adjustedChainName.toLowerCase()}%3A${tokenOutAddress}&slippageTolerancePercentage=${slippage}&partner=${feeReceiver}&feePercentage=${fee}&validate=false`; const data = await import_ky2.default.get(withdrawUrl, { headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` } }).json(); const steps = [ { chainId: chain.id, blockNumber: Number(blockNumber), from: data.tx.from, to: data.tx.to, gasLimit: "100000", gasPrice: void 0, data: data.tx.data, value: data.tx.value } ]; if (inputToken !== NATIVE_ADDRESS) { const approveAmount = await (0, import_ee_core2.getAmountToApprove)( inputToken, address, data.tx.to, amount, chain ); if (approveAmount > 0n) { steps.unshift({ chainId: chain.id, blockNumber: Number(blockNumber), from: address, to: inputToken, gasLimit: "80000", gasPrice: void 0, data: (0, import_viem2.encodeFunctionData)({ abi: import_viem2.erc20Abi, functionName: "approve", args: [data.tx.to, approveAmount] }), value: "0" }); } } return steps; }; // src/actions/swap.ts var import_ky3 = __toESM(require("ky"), 1); var import_viem3 = require("viem"); var import_ee_core3 = require("@brian-ai/ee-core"); var portalsSwap = async ({ apiUrl: inputApiUrl, apiKey, feeReceiver, fee, slippage, chain, address, inputToken, outputToken, amount }) => { const adjustedChainName = ADJUSTED_CHAINS_NAME_PORTALS[chain.name.toLowerCase()]; const publicClient = (0, import_viem3.createPublicClient)({ chain, transport: (0, import_viem3.http)() }); const blockNumber = await publicClient.getBlockNumber(); const swapUrl = `${inputApiUrl}/portal?sender=${address}&inputToken=${adjustedChainName.toLowerCase()}%3A${inputToken}&inputAmount=${amount}&outputToken=${adjustedChainName.toLowerCase()}%3A${outputToken}&slippageTolerancePercentage=${slippage}&partner=${feeReceiver}&feePercentage=${fee}&validate=false`; const data = await import_ky3.default.get(swapUrl, { headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` } }).json(); const steps = [ { chainId: chain.id, blockNumber: Number(blockNumber), from: data.tx.from, to: data.tx.to, gasLimit: "100000", gasPrice: void 0, data: data.tx.data, value: data.tx.value } ]; if (inputToken !== NATIVE_ADDRESS) { const approveAmount = await (0, import_ee_core3.getAmountToApprove)( inputToken, address, data.tx.to, amount, chain ); if (approveAmount > 0n) { steps.unshift({ chainId: chain.id, blockNumber: Number(blockNumber), from: address, to: inputToken, gasLimit: "80000", gasPrice: void 0, data: (0, import_viem3.encodeFunctionData)({ abi: import_viem3.erc20Abi, functionName: "approve", args: [data.tx.to, approveAmount] }), value: "0" }); } } return steps; }; // src/index.ts var PortalsSolver = class extends import_ee_core4.Solver { apiKey; apiUrl; feeReceiver; fee = 0.1; slippage = 0.5; constructor(allowedChains, apiUrl, apiKey, feeReceiver, fee = 0.1, slippage = 0.5) { super("portals", allowedChains); this.apiUrl = apiUrl; this.apiKey = apiKey; this.feeReceiver = feeReceiver; this.fee = fee; this.slippage = slippage; } async execute(action, data) { if (data.chain && !this.allowedChains.includes(data.chain.id)) { return Promise.reject( `[${this.name} solver] chain ${data.chain.id} not supported.` ); } switch (action) { case "swap": return { type: "write", solver: this.name, data: await portalsSwap({ ...data, apiUrl: this.apiUrl, apiKey: this.apiKey, feeReceiver: this.feeReceiver, fee: this.fee, slippage: this.slippage }) }; case "deposit": return { type: "write", solver: this.name, data: await portalsDeposit({ ...data, apiUrl: this.apiUrl, apiKey: this.apiKey, feeReceiver: this.feeReceiver, fee: this.fee, slippage: this.slippage }) }; case "withdraw": return { type: "write", solver: this.name, data: await portalsWithdraw({ ...data, apiUrl: this.apiUrl, apiKey: this.apiKey, feeReceiver: this.feeReceiver, fee: this.fee, slippage: this.slippage }) }; default: return Promise.reject( `[${this.name} solver] action "${action}" not supported.` ); } } }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { PortalsSolver });