Skip to content

Commit

Permalink
Merge pull request #12 from AstrolabDAO/feat/token/generic-token
Browse files Browse the repository at this point in the history
- Lifi: fix toAmount when not necessary (classical quote)
  • Loading branch information
scredii authored Feb 8, 2024
2 parents 560ee9d + 2df3014 commit cb7f5d4
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 15 deletions.
104 changes: 97 additions & 7 deletions src/LiFi/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
import { ITransactionRequestWithEstimate, TransactionRequest, IToolDetails, ICommonStep, ICustomContractCall } from "../types";
import qs from "qs";
import { ISwapperParams, validateQuoteParams } from "../types";
import { addEstimatesToTransactionRequest } from "../";
import { IToken as ICommonToken, IEstimate as ICommonEstimate } from "../types";

import {
addEstimatesToTransactionRequest,
IStatusResponse as ICommonStatusResponse,
OperationStatus,
} from "../";

import {
IToken as ICommonToken,
IEstimate as ICommonEstimate,
ISwapperParams,
validateQuoteParams,
ITransactionRequestWithEstimate,
TransactionRequest,
IToolDetails,
ICommonStep,
} from "../types";

// LiFi specific types
export interface ILifiContractCall {
Expand Down Expand Up @@ -179,14 +192,77 @@ interface IBestQuote extends IStep {
includedSteps?: IStep[];
}

interface TransactionStatus {
transactionId: string;
sending: SendingDetails;
receiving: ReceivingDetails;
lifiExplorerLink: string;
fromAddress: string;
toAddress: string;
tool: string;
status: string;
substatus: string;
substatusMessage: string;
metadata: Metadata;
bridgeExplorerLink: string;
}

interface SendingDetails {
txHash: string;
txLink: string;
amount: string;
token: TokenDetails;
chainId: number;
gasPrice: string;
gasUsed: string;
gasToken: TokenDetails;
gasAmount: string;
gasAmountUSD: string;
amountUSD: string;
value: string;
timestamp: number;
}

interface ReceivingDetails {
txHash: string;
txLink: string;
amount: string;
token: TokenDetails;
chainId: number;
gasPrice: string;
gasUsed: string;
gasToken: TokenDetails;
gasAmount: string;
gasAmountUSD: string;
amountUSD: string;
value: string;
timestamp: number;
}

interface TokenDetails {
address: string;
chainId: number;
symbol: string;
decimals: number;
name: string;
coinKey: string;
logoURI: string;
priceUSD: string;
}

interface Metadata {
integrator: string;
}

const apiRoot = "https://li.quest/v1";
const apiKey = process.env?.LIFI_API_KEY;

export const convertParams = (o: ISwapperParams): IQuoteParams => ({
fromToken: o.input,
fromChain: networkById[o.inputChainId],
toToken: o.output,
toAmount: o.amountWei?.toString() || undefined,
// if no contractCall, no toAmount
toAmount: o.customContractCalls?.length ? o.amountWei?.toString() || undefined : undefined,
toChain: networkById[o.outputChainId ?? o.inputChainId],
fromAmount: o.amountWei.toString(),
fromAddress: o.testPayer ?? o.payer,
Expand Down Expand Up @@ -390,16 +466,30 @@ export async function getQuote(o: ISwapperParams): Promise<IBestQuote | undefine
}
}

export function parseTransactionStatus(status: TransactionStatus): ICommonStatusResponse {
const commonStatus: ICommonStatusResponse = {
id: status.transactionId,
status: status.status as OperationStatus,
txHash: status.receiving?.txHash,
receivingTx: status.receiving.txHash,
sendingTx: status.sending.txHash,
substatus: status.substatus,
substatusMessage: status.substatusMessage,
}
return commonStatus;
}

// Check the status of your cross-chain transfers
// while (result.status !== "DONE" && result.status !== "FAILED")
// result = await getStatus(quote.tool, fromChain, toChain, tx.hash);
export async function getStatus(o: IStatusParams) {
export async function getStatus(o: IStatusParams)
: Promise<ICommonStatusResponse|undefined> {
if (!apiKey) console.warn("missing env.LIFI_API_KEY");
try {
const res = await fetch(`${apiRoot}/status?${qs.stringify(o)}`);
if (res.status >= 400)
throw new Error(`${res.status}: ${res.statusText}`);
return await res.json();
return parseTransactionStatus(await res.json());
} catch (e) {
console.error(`getStatus failed: ${e}`);
}
Expand Down
2 changes: 2 additions & 0 deletions src/Socket/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ export async function getTransactionRequest(o: ISwapperParams): Promise<ITransac
from: o.payer,
};
return addEstimatesToTransactionRequest({
totalGasUsd: 0,
totalGasWei: BigInt(0),
tr,
inputAmountWei: BigInt(o.amountWei as string),
outputAmountWei: BigInt(quote!.routes[0].toAmount),
Expand Down
73 changes: 68 additions & 5 deletions src/Squid/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import qs from "qs";
import { addEstimatesToTransactionRequest } from "../";
import { ICommonStep, ICustomContractCall, ISwapperParams, ITransactionRequestWithEstimate, TransactionRequest, validateQuoteParams } from "../types";
import { IToken as ICommonToken } from "../types";
import {
IStatusResponse as ICommonStatusResponse,
OperationStatus,
addEstimatesToTransactionRequest
} from "../";
import {
ICommonStep,
ICustomContractCall,
ISwapperParams,
ITransactionRequestWithEstimate,
TransactionRequest,
validateQuoteParams,
IToken as ICommonToken
} from "../types";

// Squid specific types
interface IQuoteParams {
Expand Down Expand Up @@ -170,6 +181,44 @@ interface IRoute {
params: IQuoteParams;
transactionRequest: ITransactionRequest;
}
type TransactionStatus = {
id: string;
status: string;
gasStatus: string;
isGMPTransaction: boolean;
axelarTransactionUrl: string;
fromChain: ChainInfo;
toChain: ChainInfo;
timeSpent: TimeSpent;
error: TransactionError;
squidTransactionStatus: string;
};

type ChainInfo = {
transactionId: string;
blockNumber: number;
callEventStatus: string;
callEventLog: any[];
chainData: any;
transactionUrl: string;
};

type TimeSpent = {
call_express_executed: number;
express_executed_confirm: number;
call_confirm: number;
call_approved: number;
express_executed_approved: number;
total: number;
approved_executed: number;
};

type TransactionError = {
message: string;
txHash: string;
chain: string;
};


const apiRoot = "https://v2.api.squidrouter.com/v2";
const apiKey = process.env?.SQUID_API_KEY;
Expand Down Expand Up @@ -357,10 +406,24 @@ export async function getQuote(o: ISwapperParams): Promise<IQuoteResponse | unde
}
}

export function parseTransactionStatus(status: TransactionStatus): ICommonStatusResponse {
const commonStatus: ICommonStatusResponse = {
id: status.id,
status: status.squidTransactionStatus as OperationStatus,
txHash: status.toChain.transactionUrl,
receivingTx: status.toChain.transactionUrl,
sendingTx: status.fromChain.transactionUrl,
substatus: status.status,
substatusMessage: status.error?.message ?? '',
}
return commonStatus;
}

// Check the status of your cross-chain transfers
// while (result.status !== "DONE" && result.status !== "FAILED")
// result = await getStatus(quote.tool, fromChain, toChain, tx.hash);
export async function getStatus(o: IStatusParams) {
export async function getStatus(o: IStatusParams)
: Promise<ICommonStatusResponse|undefined> {
if (!apiKey) console.warn("missing env.SQUID_API_KEY");
try {
const res = await fetch(`${apiRoot}/status?${qs.stringify(o)}`, {
Expand All @@ -371,7 +434,7 @@ export async function getStatus(o: IStatusParams) {
});
if (res.status >= 400)
throw new Error(`${res.status}: ${res.statusText}`);
return await res.json();
return parseTransactionStatus(await res.json());
} catch (e) {
console.error(`getStatus failed: ${e}`);
}
Expand Down
58 changes: 57 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@ import * as Squid from "./Squid";
import * as LiFi from "./LiFi";
import * as Socket from "./Socket";

import { Aggregator, AggregatorId, ICommonStep, ISwapperParams, ITransactionRequestWithEstimate, Stringifiable } from "./types";
import {
Aggregator,
AggregatorId,
ICommonStep,
ISwapperParams,
IToken,
ITransactionRequestWithEstimate,
Stringifiable
} from "./types";

// aggregatorId to aggregator mapping used by meta-aggregating getTransactionRequest
export const aggregatorById: { [key: string]: Aggregator } = {
Expand Down Expand Up @@ -144,6 +152,54 @@ export function addEstimatesToTransactionRequest(o: IEstimateParams): ITransacti
return o.tr;
}

export interface IStatusParams {
aggregatorIds: string[];
transactionId: string;
fromChainId?: string;
toChainId?: string;
txHash?: string;
}

export enum OperationStatus {
WAITING = "WAITING",
PENDING = "PENDING",
DONE = "DONE",
FAILED = "FAILED",
SUCCESS = "SUCCESS",
NEEDS_GAS = "NEEDS_GAS",
ONGOING = "ON_GOING",
PARTIAL_SUCCESS = "PARTIAL_SUCCESS",
NOT_FOUND = "NOT_FOUND"
}

export interface OperationStep extends ICommonStep {
status: OperationStatus;
via: string;
substatusMessage?: string;
}

export interface IStatusResponse {
id: string;
status: OperationStatus;
txHash?: string;
receivingTx?: string;
sendingTx?: string;
substatus?: string;
substatusMessage?: string;
}

export async function getStatus (o: IStatusParams)
: Promise<IStatusResponse|null>{
o.aggregatorIds ??= aggregatorsAvailable;
if (!o.txHash) o.txHash = o.transactionId;
let status = (await Promise.all(
o.aggregatorIds.map(async (aggregatorId) => {
const aggregator = aggregatorById[aggregatorId];
return aggregator?.getStatus?.(o);
}))).filter(tr => !!tr);
return status[0] ?? null;
}

export * from "./types";
export {
OneInch,
Expand Down
6 changes: 4 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { IStatusParams, IStatusResponse } from "src";

export interface IToken {
chainId: string;
Expand Down Expand Up @@ -75,13 +76,14 @@ export interface ITransactionRequestWithEstimate extends TransactionRequest {
estimatedSlippage?: string|number;
steps?: ICommonStep[];
approvalAddress?: string;
totalGasUsd: number;
totalGasWei: bigint;
totalGasUsd?: number;
totalGasWei?: bigint;
}

export type Aggregator = {
routerByChainId: { [key: number]: string };
getTransactionRequest: (o: ISwapperParams) => Promise<ITransactionRequestWithEstimate|undefined>;
getStatus?: (o: IStatusParams) => Promise<IStatusResponse|undefined>;
};

interface IFeeCost {
Expand Down

0 comments on commit cb7f5d4

Please sign in to comment.