@brian-ai/ee-portals-solver
Version:
> ⚠️ README: work in progress.
359 lines (350 loc) • 10.9 kB
JavaScript
;
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
});