@rhea-finance/cross-chain-aggregation-dex 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +3 -11
- package/dist/index.d.ts +3 -11
- package/dist/index.js +120 -90
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +120 -90
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -396,20 +396,12 @@ declare class AggregateDexRouter implements DexRouter {
|
|
|
396
396
|
*/
|
|
397
397
|
quote(params: QuoteParams): Promise<QuoteResult>;
|
|
398
398
|
/**
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
* @deprecated No longer needed. executeSwap automatically fetches final quote using receiveUser (depositAddress).
|
|
402
|
-
* Kept for interface compatibility only.
|
|
399
|
+
* @deprecated No longer needed. Kept for interface compatibility only.
|
|
403
400
|
*/
|
|
404
401
|
finalizeQuote(params: QuoteParams, depositAddress: string): Promise<QuoteResult>;
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
* Automatically fetches final quote using receiveUser (depositAddress) to ensure correct routerMsg and signature.
|
|
408
|
-
*/
|
|
402
|
+
private reFetchQuoteWithBalance;
|
|
403
|
+
private ensureQuoteAmountWithinBalance;
|
|
409
404
|
executeSwap(params: ExecuteParams): Promise<ExecuteResult>;
|
|
410
|
-
/**
|
|
411
|
-
* Query user token registration status in AGGREGATE_DEX contract
|
|
412
|
-
*/
|
|
413
405
|
private queryUserTokensRegistered;
|
|
414
406
|
}
|
|
415
407
|
|
package/dist/index.d.ts
CHANGED
|
@@ -396,20 +396,12 @@ declare class AggregateDexRouter implements DexRouter {
|
|
|
396
396
|
*/
|
|
397
397
|
quote(params: QuoteParams): Promise<QuoteResult>;
|
|
398
398
|
/**
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
* @deprecated No longer needed. executeSwap automatically fetches final quote using receiveUser (depositAddress).
|
|
402
|
-
* Kept for interface compatibility only.
|
|
399
|
+
* @deprecated No longer needed. Kept for interface compatibility only.
|
|
403
400
|
*/
|
|
404
401
|
finalizeQuote(params: QuoteParams, depositAddress: string): Promise<QuoteResult>;
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
* Automatically fetches final quote using receiveUser (depositAddress) to ensure correct routerMsg and signature.
|
|
408
|
-
*/
|
|
402
|
+
private reFetchQuoteWithBalance;
|
|
403
|
+
private ensureQuoteAmountWithinBalance;
|
|
409
404
|
executeSwap(params: ExecuteParams): Promise<ExecuteResult>;
|
|
410
|
-
/**
|
|
411
|
-
* Query user token registration status in AGGREGATE_DEX contract
|
|
412
|
-
*/
|
|
413
405
|
private queryUserTokensRegistered;
|
|
414
406
|
}
|
|
415
407
|
|
package/dist/index.js
CHANGED
|
@@ -625,14 +625,6 @@ var AggregateDexRouter = class {
|
|
|
625
625
|
}
|
|
626
626
|
const slippageBps = convertSlippageToBasisPoints(slippage);
|
|
627
627
|
const slippageDecimalForApi = slippageBps / 1e4;
|
|
628
|
-
logger.debug("AggregateDexRouter quote - Calling swapMultiDexPath:", {
|
|
629
|
-
tokenIn: normalizedTokenIn,
|
|
630
|
-
tokenOut: normalizedTokenOut,
|
|
631
|
-
amountIn,
|
|
632
|
-
slippage: slippageDecimalForApi,
|
|
633
|
-
sender,
|
|
634
|
-
recipient
|
|
635
|
-
});
|
|
636
628
|
const response = await this.swapMultiDexPathAdapter.swapMultiDexPath({
|
|
637
629
|
amountIn: String(amountIn),
|
|
638
630
|
tokenIn: normalizedTokenIn,
|
|
@@ -642,11 +634,6 @@ var AggregateDexRouter = class {
|
|
|
642
634
|
user: sender,
|
|
643
635
|
receiveUser: recipient
|
|
644
636
|
});
|
|
645
|
-
logger.debug("AggregateDexRouter quote - swapMultiDexPath response:", {
|
|
646
|
-
result_code: response?.result_code,
|
|
647
|
-
result_message: response?.result_message,
|
|
648
|
-
hasData: !!response?.result_data
|
|
649
|
-
});
|
|
650
637
|
if (response.result_code !== 0 || !response.result_data) {
|
|
651
638
|
return {
|
|
652
639
|
success: false,
|
|
@@ -698,10 +685,7 @@ var AggregateDexRouter = class {
|
|
|
698
685
|
}
|
|
699
686
|
}
|
|
700
687
|
/**
|
|
701
|
-
*
|
|
702
|
-
*
|
|
703
|
-
* @deprecated No longer needed. executeSwap automatically fetches final quote using receiveUser (depositAddress).
|
|
704
|
-
* Kept for interface compatibility only.
|
|
688
|
+
* @deprecated No longer needed. Kept for interface compatibility only.
|
|
705
689
|
*/
|
|
706
690
|
async finalizeQuote(params, depositAddress) {
|
|
707
691
|
if (!requiresRecipient(params)) {
|
|
@@ -712,10 +696,70 @@ var AggregateDexRouter = class {
|
|
|
712
696
|
recipient: depositAddress
|
|
713
697
|
});
|
|
714
698
|
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
699
|
+
async reFetchQuoteWithBalance(quoteParams, actualBalance, context) {
|
|
700
|
+
const balanceBig = new Big2__default.default(actualBalance);
|
|
701
|
+
const adjustedParams = {
|
|
702
|
+
...quoteParams,
|
|
703
|
+
amountIn: balanceBig.toFixed(0)
|
|
704
|
+
};
|
|
705
|
+
logger.warn(`AggregateDexRouter - ${context}: re-fetching quote with actual balance:`, {
|
|
706
|
+
requestedAmount: quoteParams.amountIn,
|
|
707
|
+
actualBalance
|
|
708
|
+
});
|
|
709
|
+
const adjustedQuote = await this.quote(adjustedParams);
|
|
710
|
+
if (adjustedQuote.success && adjustedQuote.routerMsg && adjustedQuote.signature) {
|
|
711
|
+
return adjustedQuote;
|
|
712
|
+
} else {
|
|
713
|
+
throw new Error(`Failed to re-fetch quote with actual balance: ${adjustedQuote.error || "Unknown error"}`);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
async ensureQuoteAmountWithinBalance(quoteParams, actualBalance, context) {
|
|
717
|
+
const requestedAmountBig = new Big2__default.default(quoteParams.amountIn);
|
|
718
|
+
const balanceBig = new Big2__default.default(actualBalance);
|
|
719
|
+
const isNativeNear = (quoteParams.tokenIn.symbol === "NEAR" || quoteParams.tokenIn.address === "near" || !quoteParams.tokenIn.address && quoteParams.tokenIn.symbol === "NEAR") && quoteParams.tokenIn.address !== this.wrapNearContractId;
|
|
720
|
+
let effectiveBalanceBig = balanceBig;
|
|
721
|
+
let effectiveBalanceStr = actualBalance;
|
|
722
|
+
if (isNativeNear) {
|
|
723
|
+
const reserveAmount = new Big2__default.default("50000000000000000000000");
|
|
724
|
+
if (balanceBig.gt(reserveAmount)) {
|
|
725
|
+
effectiveBalanceBig = balanceBig.minus(reserveAmount);
|
|
726
|
+
effectiveBalanceStr = effectiveBalanceBig.toFixed(0);
|
|
727
|
+
} else {
|
|
728
|
+
effectiveBalanceBig = new Big2__default.default(0);
|
|
729
|
+
effectiveBalanceStr = "0";
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
if (requestedAmountBig.gt(effectiveBalanceBig) && balanceBig.gt(0)) {
|
|
733
|
+
return await this.reFetchQuoteWithBalance(quoteParams, effectiveBalanceStr, `${context} (requested amount exceeds available balance${isNativeNear ? " minus gas reserve" : ""})`);
|
|
734
|
+
}
|
|
735
|
+
if (balanceBig.gt(0) && requestedAmountBig.lt(balanceBig)) {
|
|
736
|
+
const diff = balanceBig.minus(requestedAmountBig);
|
|
737
|
+
const diffPercent = diff.div(balanceBig).times(100);
|
|
738
|
+
const isMaxSwap = diffPercent.lt(0.1) || diff.lt(1e3);
|
|
739
|
+
if (isMaxSwap) {
|
|
740
|
+
return await this.reFetchQuoteWithBalance(quoteParams, effectiveBalanceStr, `${context} (MAX swap detected, using ${isNativeNear ? "balance minus gas reserve" : "actual balance"})`);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
const quote = await this.quote(quoteParams);
|
|
744
|
+
if (!quote.success) {
|
|
745
|
+
throw new Error(`Failed to fetch quote: ${quote.error || "Unknown error"}`);
|
|
746
|
+
}
|
|
747
|
+
if (quote.amountIn !== quoteParams.amountIn) {
|
|
748
|
+
const apiAmountBig = new Big2__default.default(quote.amountIn);
|
|
749
|
+
if (apiAmountBig.gt(effectiveBalanceBig) && balanceBig.gt(0)) {
|
|
750
|
+
return await this.reFetchQuoteWithBalance(quoteParams, effectiveBalanceStr, `${context} (API returned amount_in exceeds available balance)`);
|
|
751
|
+
}
|
|
752
|
+
if (apiAmountBig.lt(balanceBig) && balanceBig.gt(0)) {
|
|
753
|
+
const diff = balanceBig.minus(apiAmountBig);
|
|
754
|
+
const diffPercent = diff.div(balanceBig).times(100);
|
|
755
|
+
const isMaxSwap = diffPercent.lt(0.1) || diff.lt(1e3);
|
|
756
|
+
if (isMaxSwap) {
|
|
757
|
+
return await this.reFetchQuoteWithBalance(quoteParams, effectiveBalanceStr, `${context} (API returned amount_in close to balance, MAX swap detected)`);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
return quote;
|
|
762
|
+
}
|
|
719
763
|
async executeSwap(params) {
|
|
720
764
|
try {
|
|
721
765
|
if (!requiresRecipientInExecute(params)) {
|
|
@@ -743,16 +787,17 @@ var AggregateDexRouter = class {
|
|
|
743
787
|
error: `receiveUser appears to be an EVM address (${receiveUser}). For NEAR chain swaps, depositAddress must be a NEAR account (64 hex chars or .near format)`
|
|
744
788
|
};
|
|
745
789
|
}
|
|
746
|
-
logger.debug("AggregateDexRouter - executeSwap params:", {
|
|
747
|
-
sender,
|
|
748
|
-
receiveUser,
|
|
749
|
-
tokenIn: quote.tokenIn.address,
|
|
750
|
-
tokenOut: quote.tokenOut.address,
|
|
751
|
-
amountIn: quote.amountIn,
|
|
752
|
-
tokens: quote.tokens,
|
|
753
|
-
dexs: quote.dexs
|
|
754
|
-
});
|
|
755
790
|
const slippage = quote.slippage || 5e-3;
|
|
791
|
+
let tokenBalanceAtExecution = "0";
|
|
792
|
+
try {
|
|
793
|
+
const balanceResult = await this.nearChainAdapter.view({
|
|
794
|
+
contractId: quote.tokenIn.address,
|
|
795
|
+
methodName: "ft_balance_of",
|
|
796
|
+
args: { account_id: sender }
|
|
797
|
+
});
|
|
798
|
+
tokenBalanceAtExecution = balanceResult || "0";
|
|
799
|
+
} catch (e) {
|
|
800
|
+
}
|
|
756
801
|
const finalQuoteParams = {
|
|
757
802
|
tokenIn: quote.tokenIn,
|
|
758
803
|
tokenOut: quote.tokenOut,
|
|
@@ -763,13 +808,11 @@ var AggregateDexRouter = class {
|
|
|
763
808
|
};
|
|
764
809
|
let finalQuote;
|
|
765
810
|
try {
|
|
766
|
-
finalQuote = await this.
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
};
|
|
772
|
-
}
|
|
811
|
+
finalQuote = await this.ensureQuoteAmountWithinBalance(
|
|
812
|
+
finalQuoteParams,
|
|
813
|
+
tokenBalanceAtExecution,
|
|
814
|
+
"Re-fetching quote with receiveUser"
|
|
815
|
+
);
|
|
773
816
|
} catch (error) {
|
|
774
817
|
logger.error("AggregateDexRouter - Failed to fetch quote with receiveUser:", error);
|
|
775
818
|
return {
|
|
@@ -785,12 +828,6 @@ var AggregateDexRouter = class {
|
|
|
785
828
|
error: `Quote fetched with receiveUser="${receiveUser}" is missing routerMsg or signature.`
|
|
786
829
|
};
|
|
787
830
|
}
|
|
788
|
-
logger.debug("AggregateDexRouter - Successfully fetched final quote:", {
|
|
789
|
-
receiveUser,
|
|
790
|
-
quoteRecipient: finalQuote.recipient,
|
|
791
|
-
routerMsgLength: routerMsg.length,
|
|
792
|
-
signatureLength: signature.length
|
|
793
|
-
});
|
|
794
831
|
const tokens = finalQuote.tokens || [];
|
|
795
832
|
const dexs = finalQuote.dexs || [];
|
|
796
833
|
const transactions = [];
|
|
@@ -805,7 +842,7 @@ var AggregateDexRouter = class {
|
|
|
805
842
|
return null;
|
|
806
843
|
}
|
|
807
844
|
};
|
|
808
|
-
const isNativeNear = finalQuote.tokenIn.symbol === "NEAR" || finalQuote.tokenIn.address === "near" || !finalQuote.tokenIn.address && finalQuote.tokenIn.symbol === "NEAR";
|
|
845
|
+
const isNativeNear = (finalQuote.tokenIn.symbol === "NEAR" || finalQuote.tokenIn.address === "near" || !finalQuote.tokenIn.address && finalQuote.tokenIn.symbol === "NEAR") && finalQuote.tokenIn.address !== this.wrapNearContractId;
|
|
809
846
|
if (isNativeNear) {
|
|
810
847
|
const wrapNearStorageBalance = await getStorageBalance(
|
|
811
848
|
this.wrapNearContractId,
|
|
@@ -852,11 +889,6 @@ var AggregateDexRouter = class {
|
|
|
852
889
|
}
|
|
853
890
|
});
|
|
854
891
|
if (receiveUser && receiveUser !== sender) {
|
|
855
|
-
logger.debug("AggregateDexRouter - Checking receiveUser registration in tokenOut:", {
|
|
856
|
-
receiveUser,
|
|
857
|
-
tokenOut: finalQuote.tokenOut.address,
|
|
858
|
-
tokenOutSymbol: finalQuote.tokenOut.symbol
|
|
859
|
-
});
|
|
860
892
|
const receiveUserStorageBalance = await getStorageBalance(
|
|
861
893
|
finalQuote.tokenOut.address,
|
|
862
894
|
receiveUser
|
|
@@ -869,12 +901,6 @@ var AggregateDexRouter = class {
|
|
|
869
901
|
return null;
|
|
870
902
|
});
|
|
871
903
|
if (!receiveUserStorageBalance) {
|
|
872
|
-
logger.debug("AggregateDexRouter - receiveUser not registered in tokenOut, adding registration transaction:", {
|
|
873
|
-
receiveUser,
|
|
874
|
-
tokenOut: finalQuote.tokenOut.address,
|
|
875
|
-
tokenOutSymbol: finalQuote.tokenOut.symbol,
|
|
876
|
-
storageCost: this.NEW_ACCOUNT_STORAGE_COST
|
|
877
|
-
});
|
|
878
904
|
transactions.push({
|
|
879
905
|
contractId: finalQuote.tokenOut.address,
|
|
880
906
|
methodName: "storage_deposit",
|
|
@@ -920,7 +946,7 @@ var AggregateDexRouter = class {
|
|
|
920
946
|
const depositPerToken = new Big2__default.default("0.005").mul(
|
|
921
947
|
new Big2__default.default("1000000000000000000000000")
|
|
922
948
|
);
|
|
923
|
-
const
|
|
949
|
+
const totalDeposit = depositPerToken.mul(unregisteredTokens.length);
|
|
924
950
|
transactions.push({
|
|
925
951
|
contractId: this.aggregateDexContractId,
|
|
926
952
|
methodName: "tokens_storage_deposit",
|
|
@@ -929,50 +955,57 @@ var AggregateDexRouter = class {
|
|
|
929
955
|
tokens: unregisteredTokens
|
|
930
956
|
},
|
|
931
957
|
gas: "30000000000000",
|
|
932
|
-
expandDeposit:
|
|
958
|
+
expandDeposit: totalDeposit.toFixed(0)
|
|
933
959
|
});
|
|
934
960
|
}
|
|
935
961
|
}
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
962
|
+
try {
|
|
963
|
+
const balanceResult = await this.nearChainAdapter.view({
|
|
964
|
+
contractId: finalQuote.tokenIn.address,
|
|
965
|
+
methodName: "ft_balance_of",
|
|
966
|
+
args: { account_id: sender }
|
|
967
|
+
});
|
|
968
|
+
tokenBalanceAtExecution = balanceResult || "0";
|
|
969
|
+
} catch (e) {
|
|
970
|
+
}
|
|
971
|
+
const finalBalanceQuoteParams = {
|
|
972
|
+
tokenIn: finalQuote.tokenIn,
|
|
973
|
+
tokenOut: finalQuote.tokenOut,
|
|
974
|
+
amountIn: finalQuote.amountIn,
|
|
975
|
+
slippage,
|
|
976
|
+
sender,
|
|
977
|
+
recipient: receiveUser
|
|
978
|
+
};
|
|
979
|
+
let finalQuoteForExecution;
|
|
980
|
+
try {
|
|
981
|
+
finalQuoteForExecution = await this.ensureQuoteAmountWithinBalance(
|
|
982
|
+
finalBalanceQuoteParams,
|
|
983
|
+
tokenBalanceAtExecution,
|
|
984
|
+
"Final balance check before execution"
|
|
985
|
+
);
|
|
986
|
+
} catch (error) {
|
|
987
|
+
logger.error("AggregateDexRouter - Failed final balance check:", error);
|
|
988
|
+
return {
|
|
989
|
+
success: false,
|
|
990
|
+
error: `Failed final balance check: ${error?.message || "Unknown error"}`
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
const finalAmountToTransfer = finalQuoteForExecution.amountIn;
|
|
994
|
+
const finalMsgString = JSON.stringify({
|
|
995
|
+
msg: finalQuoteForExecution.routerMsg,
|
|
996
|
+
signature: finalQuoteForExecution.signature
|
|
939
997
|
});
|
|
940
998
|
transactions.push({
|
|
941
999
|
contractId: finalQuote.tokenIn.address,
|
|
942
1000
|
methodName: "ft_transfer_call",
|
|
943
1001
|
args: {
|
|
944
1002
|
receiver_id: this.aggregateDexContractId,
|
|
945
|
-
amount:
|
|
946
|
-
msg:
|
|
1003
|
+
amount: finalAmountToTransfer,
|
|
1004
|
+
msg: finalMsgString
|
|
947
1005
|
},
|
|
948
1006
|
gas: "300000000000000",
|
|
949
1007
|
expandDeposit: this.ONE_YOCTO_NEAR
|
|
950
1008
|
});
|
|
951
|
-
const totalDeposit = transactions.reduce((sum, tx) => {
|
|
952
|
-
if (tx.expandDeposit) {
|
|
953
|
-
return sum.plus(tx.expandDeposit);
|
|
954
|
-
}
|
|
955
|
-
return sum;
|
|
956
|
-
}, new Big2__default.default(0));
|
|
957
|
-
logger.debug("AggregateDexRouter - Executing swap (following mature codebase logic):", {
|
|
958
|
-
contractId: finalQuote.tokenIn.address,
|
|
959
|
-
receiver_id: this.aggregateDexContractId,
|
|
960
|
-
amount: finalQuote.amountIn,
|
|
961
|
-
transactionsCount: transactions.length,
|
|
962
|
-
sender,
|
|
963
|
-
receiveUser,
|
|
964
|
-
tokens: tokens.length,
|
|
965
|
-
dexs: dexs.length,
|
|
966
|
-
totalDepositYocto: totalDeposit.toFixed(0),
|
|
967
|
-
totalDepositNEAR: totalDeposit.div(new Big2__default.default("1000000000000000000000000")).toFixed(6),
|
|
968
|
-
transactions: transactions.map((tx, idx) => ({
|
|
969
|
-
index: idx,
|
|
970
|
-
contractId: tx.contractId,
|
|
971
|
-
methodName: tx.methodName,
|
|
972
|
-
expandDeposit: tx.expandDeposit,
|
|
973
|
-
expandDepositNEAR: tx.expandDeposit ? new Big2__default.default(tx.expandDeposit).div(new Big2__default.default("1000000000000000000000000")).toFixed(6) : "0"
|
|
974
|
-
}))
|
|
975
|
-
});
|
|
976
1009
|
const result = await this.nearChainAdapter.call({
|
|
977
1010
|
transactions
|
|
978
1011
|
});
|
|
@@ -996,9 +1029,6 @@ var AggregateDexRouter = class {
|
|
|
996
1029
|
};
|
|
997
1030
|
}
|
|
998
1031
|
}
|
|
999
|
-
/**
|
|
1000
|
-
* Query user token registration status in AGGREGATE_DEX contract
|
|
1001
|
-
*/
|
|
1002
1032
|
async queryUserTokensRegistered({
|
|
1003
1033
|
user,
|
|
1004
1034
|
tokens
|