@stableflow/bridges 3.0.3 → 3.1.0
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 +148 -11
- package/dist/index.d.ts +148 -11
- package/dist/index.js +366 -44
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +365 -46
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -189,6 +189,7 @@ var OneClickService = class {
|
|
|
189
189
|
appFees = [],
|
|
190
190
|
swapType = "EXACT_INPUT",
|
|
191
191
|
isProxy = true,
|
|
192
|
+
slippageTolerance,
|
|
192
193
|
...restParams
|
|
193
194
|
} = params;
|
|
194
195
|
const _quoteType = `OneClickService ${fromToken?.chainName}->${toToken?.chainName}`;
|
|
@@ -206,7 +207,8 @@ var OneClickService = class {
|
|
|
206
207
|
...appFees
|
|
207
208
|
],
|
|
208
209
|
referral: "stableflow",
|
|
209
|
-
amount: amountWei
|
|
210
|
+
amount: amountWei,
|
|
211
|
+
slippageTolerance: slippageTolerance * 100
|
|
210
212
|
};
|
|
211
213
|
if (swapType === "EXACT_OUTPUT") {
|
|
212
214
|
quoteParams.amount = Big__default.default(amountWei || 0).div(10 ** fromToken.decimals).times(10 ** toToken.decimals).toFixed(0);
|
|
@@ -4846,6 +4848,7 @@ var FraxZero2OneClickService = class extends FraxZeroService {
|
|
|
4846
4848
|
refundTo: middleChainRecipientAddress,
|
|
4847
4849
|
wallet: middleChainWallet,
|
|
4848
4850
|
appFees: [
|
|
4851
|
+
...params.appFees || [],
|
|
4849
4852
|
{
|
|
4850
4853
|
recipient: "reffer.near",
|
|
4851
4854
|
// No bridge fee will be charged temporarily
|
|
@@ -5065,6 +5068,7 @@ var OneClick2FraxZeroService = class extends FraxZeroService {
|
|
|
5065
5068
|
isProxy: true,
|
|
5066
5069
|
recipient: middleChainRecipientAddress,
|
|
5067
5070
|
appFees: [
|
|
5071
|
+
...params.appFees || [],
|
|
5068
5072
|
{
|
|
5069
5073
|
recipient: "reffer.near",
|
|
5070
5074
|
// No bridge fee will be charged temporarily
|
|
@@ -5420,6 +5424,7 @@ var OneClickUsdt0Service = class {
|
|
|
5420
5424
|
isProxy: true,
|
|
5421
5425
|
recipient: middleChainRecipientAddress,
|
|
5422
5426
|
appFees: [
|
|
5427
|
+
...params.appFees || [],
|
|
5423
5428
|
{
|
|
5424
5429
|
recipient: "reffer.near",
|
|
5425
5430
|
// No bridge fee will be charged temporarily
|
|
@@ -5667,11 +5672,228 @@ var ServiceMap = {
|
|
|
5667
5672
|
[core.Service.OneClickUsdt0]: from_oneclick_default2,
|
|
5668
5673
|
[core.Service.Native]: native_default
|
|
5669
5674
|
};
|
|
5675
|
+
var OVERRIDE_KEYS = /* @__PURE__ */ new Set([
|
|
5676
|
+
"value",
|
|
5677
|
+
"gasLimit",
|
|
5678
|
+
"gasPrice",
|
|
5679
|
+
"maxFeePerGas",
|
|
5680
|
+
"maxPriorityFeePerGas",
|
|
5681
|
+
"nonce",
|
|
5682
|
+
"from",
|
|
5683
|
+
"type",
|
|
5684
|
+
"accessList",
|
|
5685
|
+
"chainId",
|
|
5686
|
+
"customData",
|
|
5687
|
+
"blockTag"
|
|
5688
|
+
]);
|
|
5689
|
+
var toDecimalString = (v) => {
|
|
5690
|
+
if (v === void 0 || v === null) {
|
|
5691
|
+
return "0";
|
|
5692
|
+
}
|
|
5693
|
+
if (typeof v === "bigint") {
|
|
5694
|
+
return v.toString();
|
|
5695
|
+
}
|
|
5696
|
+
if (typeof v === "number") {
|
|
5697
|
+
return Math.trunc(v).toString();
|
|
5698
|
+
}
|
|
5699
|
+
return String(v);
|
|
5700
|
+
};
|
|
5701
|
+
var assertEvm = (token) => {
|
|
5702
|
+
if (!token || token.chainType !== "evm") {
|
|
5703
|
+
throw new Error("API-driven custody currently supports EVM chains only");
|
|
5704
|
+
}
|
|
5705
|
+
};
|
|
5706
|
+
var getSendAmountWei = (serviceType, quote) => {
|
|
5707
|
+
const { isExactOutput } = getQuoteModes({
|
|
5708
|
+
quoteData: quote,
|
|
5709
|
+
bridgeStore: { quoteDataService: serviceType }
|
|
5710
|
+
});
|
|
5711
|
+
if (isExactOutput) {
|
|
5712
|
+
return quote?.quote?.minAmountIn;
|
|
5713
|
+
}
|
|
5714
|
+
return quote?.quoteParam?.amountWei;
|
|
5715
|
+
};
|
|
5716
|
+
var encodeContractCall = (sendParam) => {
|
|
5717
|
+
const { contract, method, param } = sendParam;
|
|
5718
|
+
if (!contract?.interface || contract?.target === void 0) {
|
|
5719
|
+
throw new Error("Invalid sendParam: missing contract interface/target");
|
|
5720
|
+
}
|
|
5721
|
+
const to = typeof contract.target === "string" ? contract.target : String(contract.target);
|
|
5722
|
+
let args = Array.isArray(param) ? param : [];
|
|
5723
|
+
let value;
|
|
5724
|
+
let gasLimit;
|
|
5725
|
+
if (args.length > 0) {
|
|
5726
|
+
const last = args[args.length - 1];
|
|
5727
|
+
const isOverride = last !== null && typeof last === "object" && !Array.isArray(last) && Object.keys(last).length > 0 && Object.keys(last).every((k) => OVERRIDE_KEYS.has(k));
|
|
5728
|
+
if (isOverride) {
|
|
5729
|
+
args = args.slice(0, -1);
|
|
5730
|
+
value = last.value;
|
|
5731
|
+
gasLimit = last.gasLimit;
|
|
5732
|
+
}
|
|
5733
|
+
}
|
|
5734
|
+
const data = contract.interface.encodeFunctionData(method, args);
|
|
5735
|
+
return {
|
|
5736
|
+
to,
|
|
5737
|
+
data,
|
|
5738
|
+
value: toDecimalString(value),
|
|
5739
|
+
gasLimit: gasLimit === void 0 || gasLimit === null ? void 0 : toDecimalString(gasLimit)
|
|
5740
|
+
};
|
|
5741
|
+
};
|
|
5742
|
+
var buildTransferTx = (params) => {
|
|
5743
|
+
const { chainId, from, fromToken, depositAddress, amountWei } = params;
|
|
5744
|
+
if (!depositAddress) {
|
|
5745
|
+
throw new Error("Quote has no depositAddress to build transfer transaction");
|
|
5746
|
+
}
|
|
5747
|
+
if (fromToken.contractAddress === "eth") {
|
|
5748
|
+
return {
|
|
5749
|
+
chainId,
|
|
5750
|
+
from,
|
|
5751
|
+
to: depositAddress,
|
|
5752
|
+
data: "0x",
|
|
5753
|
+
value: toDecimalString(amountWei)
|
|
5754
|
+
};
|
|
5755
|
+
}
|
|
5756
|
+
const iface = new ethers.ethers.Interface(core.erc20Abi);
|
|
5757
|
+
const data = iface.encodeFunctionData("transfer", [depositAddress, amountWei]);
|
|
5758
|
+
return {
|
|
5759
|
+
chainId,
|
|
5760
|
+
from,
|
|
5761
|
+
to: fromToken.contractAddress,
|
|
5762
|
+
data,
|
|
5763
|
+
value: "0"
|
|
5764
|
+
};
|
|
5765
|
+
};
|
|
5766
|
+
var buildSendTx = (serviceType, quote) => {
|
|
5767
|
+
const fromToken = quote?.quoteParam?.fromToken;
|
|
5768
|
+
assertEvm(fromToken);
|
|
5769
|
+
const chainId = fromToken.chainId;
|
|
5770
|
+
const from = quote?.quoteParam?.refundTo;
|
|
5771
|
+
const sendParam = quote?.sendParam;
|
|
5772
|
+
if (sendParam?.txRequest) {
|
|
5773
|
+
const txRequest = sendParam.txRequest;
|
|
5774
|
+
return {
|
|
5775
|
+
chainId,
|
|
5776
|
+
from,
|
|
5777
|
+
to: txRequest.target,
|
|
5778
|
+
data: txRequest.calldata,
|
|
5779
|
+
value: toDecimalString(txRequest.value),
|
|
5780
|
+
gasLimit: txRequest.gasLimit === void 0 || txRequest.gasLimit === null ? void 0 : toDecimalString(txRequest.gasLimit)
|
|
5781
|
+
};
|
|
5782
|
+
}
|
|
5783
|
+
const { isOneClickService } = getQuoteModes({
|
|
5784
|
+
quoteData: quote,
|
|
5785
|
+
bridgeStore: { quoteDataService: serviceType }
|
|
5786
|
+
});
|
|
5787
|
+
if (isOneClickService) {
|
|
5788
|
+
if (sendParam) {
|
|
5789
|
+
return { chainId, from, ...encodeContractCall(sendParam) };
|
|
5790
|
+
}
|
|
5791
|
+
return buildTransferTx({
|
|
5792
|
+
chainId,
|
|
5793
|
+
from,
|
|
5794
|
+
fromToken,
|
|
5795
|
+
depositAddress: quote?.quote?.depositAddress,
|
|
5796
|
+
amountWei: getSendAmountWei(serviceType, quote)
|
|
5797
|
+
});
|
|
5798
|
+
}
|
|
5799
|
+
if (!sendParam) {
|
|
5800
|
+
throw new Error("Quote has no sendParam to build transaction");
|
|
5801
|
+
}
|
|
5802
|
+
return { chainId, from, ...encodeContractCall(sendParam) };
|
|
5803
|
+
};
|
|
5804
|
+
var buildApproveTx = (serviceType, quote) => {
|
|
5805
|
+
if (!quote?.needApprove) {
|
|
5806
|
+
return {};
|
|
5807
|
+
}
|
|
5808
|
+
const fromToken = quote?.quoteParam?.fromToken;
|
|
5809
|
+
assertEvm(fromToken);
|
|
5810
|
+
if (fromToken.contractAddress === "eth") {
|
|
5811
|
+
return {};
|
|
5812
|
+
}
|
|
5813
|
+
const chainId = fromToken.chainId;
|
|
5814
|
+
const from = quote?.quoteParam?.refundTo;
|
|
5815
|
+
const spender = quote?.approveSpender;
|
|
5816
|
+
if (!spender) {
|
|
5817
|
+
throw new Error("Quote requires approval but has no approveSpender");
|
|
5818
|
+
}
|
|
5819
|
+
const amountWei = getSendAmountWei(serviceType, quote);
|
|
5820
|
+
const iface = new ethers.ethers.Interface(core.erc20Abi);
|
|
5821
|
+
const approveTx = {
|
|
5822
|
+
chainId,
|
|
5823
|
+
from,
|
|
5824
|
+
to: fromToken.contractAddress,
|
|
5825
|
+
data: iface.encodeFunctionData("approve", [spender, amountWei]),
|
|
5826
|
+
value: "0"
|
|
5827
|
+
};
|
|
5828
|
+
const result = { approveTx };
|
|
5829
|
+
if (fromToken.chainName === "Ethereum") {
|
|
5830
|
+
result.approveResetTx = {
|
|
5831
|
+
chainId,
|
|
5832
|
+
from,
|
|
5833
|
+
to: fromToken.contractAddress,
|
|
5834
|
+
data: iface.encodeFunctionData("approve", [spender, "0"]),
|
|
5835
|
+
value: "0"
|
|
5836
|
+
};
|
|
5837
|
+
}
|
|
5838
|
+
return result;
|
|
5839
|
+
};
|
|
5840
|
+
var buildPermitTypedData = async (params) => {
|
|
5841
|
+
const { permitToken, permitAmountWei, permitSpender, owner } = params;
|
|
5842
|
+
assertEvm(permitToken);
|
|
5843
|
+
if (!owner) {
|
|
5844
|
+
throw new Error("buildPermitTypedData requires the permit owner address");
|
|
5845
|
+
}
|
|
5846
|
+
const provider = utilsEvm.evmRpcFallbackProvider(permitToken);
|
|
5847
|
+
const erc20 = new ethers.ethers.Contract(permitToken.contractAddress, core.erc20Abi, provider);
|
|
5848
|
+
const [nonce, name] = await Promise.all([
|
|
5849
|
+
erc20.nonces(owner),
|
|
5850
|
+
erc20.name()
|
|
5851
|
+
]);
|
|
5852
|
+
const version = permitToken.symbol === "USDC" ? "2" : "1";
|
|
5853
|
+
const deadline = Math.floor(Date.now() / 1e3) + 60 * 60 * 24 * 3;
|
|
5854
|
+
const domain = {
|
|
5855
|
+
name,
|
|
5856
|
+
version,
|
|
5857
|
+
chainId: Number(permitToken.chainId),
|
|
5858
|
+
verifyingContract: permitToken.contractAddress
|
|
5859
|
+
};
|
|
5860
|
+
const types = {
|
|
5861
|
+
Permit: [
|
|
5862
|
+
{ name: "owner", type: "address" },
|
|
5863
|
+
{ name: "spender", type: "address" },
|
|
5864
|
+
{ name: "value", type: "uint256" },
|
|
5865
|
+
{ name: "nonce", type: "uint256" },
|
|
5866
|
+
{ name: "deadline", type: "uint256" }
|
|
5867
|
+
]
|
|
5868
|
+
};
|
|
5869
|
+
const values = {
|
|
5870
|
+
owner,
|
|
5871
|
+
spender: permitSpender,
|
|
5872
|
+
value: toDecimalString(permitAmountWei),
|
|
5873
|
+
nonce: nonce.toString(),
|
|
5874
|
+
deadline
|
|
5875
|
+
};
|
|
5876
|
+
return {
|
|
5877
|
+
domain,
|
|
5878
|
+
types,
|
|
5879
|
+
values,
|
|
5880
|
+
deadline,
|
|
5881
|
+
nonce: Number(nonce),
|
|
5882
|
+
token: permitToken.contractAddress,
|
|
5883
|
+
spender: permitSpender,
|
|
5884
|
+
owner
|
|
5885
|
+
};
|
|
5886
|
+
};
|
|
5887
|
+
|
|
5888
|
+
// src/sfa.ts
|
|
5670
5889
|
var submitOthersTx = (requestBody) => {
|
|
5671
5890
|
return core.postRequest("/v0/trade/add", requestBody);
|
|
5672
5891
|
};
|
|
5673
|
-
var BridgeSFA = class {
|
|
5892
|
+
var BridgeSFA = class _BridgeSFA {
|
|
5674
5893
|
static async getAllQuote(params) {
|
|
5894
|
+
const cs = new core.Csl(core.OpenAPI.DEBUG);
|
|
5895
|
+
const csl = cs.log;
|
|
5896
|
+
csl("BridgeSFA.getAllQuote", "blue-400", "params: %o", params);
|
|
5675
5897
|
const results = [];
|
|
5676
5898
|
let { minInputAmount = "1", disabledServices } = params;
|
|
5677
5899
|
if (Big__default.default(minInputAmount).lte(0)) {
|
|
@@ -5701,7 +5923,6 @@ var BridgeSFA = class {
|
|
|
5701
5923
|
core.Service.FraxZeroOneClick,
|
|
5702
5924
|
core.Service.OneClickFraxZero
|
|
5703
5925
|
].includes(service)) {
|
|
5704
|
-
_params.slippageTolerance = params.slippageTolerance * 100;
|
|
5705
5926
|
_params.originAsset = params.fromToken.assetId;
|
|
5706
5927
|
_params.destinationAsset = params.toToken.assetId;
|
|
5707
5928
|
_params.refundType = "ORIGIN_CHAIN";
|
|
@@ -5734,6 +5955,7 @@ var BridgeSFA = class {
|
|
|
5734
5955
|
return;
|
|
5735
5956
|
}
|
|
5736
5957
|
const quoteParams = formatQuoteParams(_service);
|
|
5958
|
+
csl("BridgeSFA.getAllQuote", "blue-400", "%s quoteParams: %o", _service, quoteParams);
|
|
5737
5959
|
quoteServices.push({
|
|
5738
5960
|
service: _service,
|
|
5739
5961
|
quote: () => {
|
|
@@ -5786,6 +6008,7 @@ var BridgeSFA = class {
|
|
|
5786
6008
|
}
|
|
5787
6009
|
return results;
|
|
5788
6010
|
}
|
|
6011
|
+
csl("BridgeSFA.getAllQuote", "blue-400", "quoteServices: %o", quoteServices);
|
|
5789
6012
|
const promises = [];
|
|
5790
6013
|
for (const quoteService of quoteServices) {
|
|
5791
6014
|
const promise = (async () => {
|
|
@@ -5827,12 +6050,11 @@ var BridgeSFA = class {
|
|
|
5827
6050
|
const sendParams = {
|
|
5828
6051
|
wallet
|
|
5829
6052
|
};
|
|
5830
|
-
const { isExactOutput, isOneClickService
|
|
6053
|
+
const { isExactOutput, isOneClickService } = getQuoteModes({
|
|
5831
6054
|
quoteData: quote,
|
|
5832
6055
|
bridgeStore: { quoteDataService: serviceType }
|
|
5833
6056
|
});
|
|
5834
6057
|
const fromToken = quote.quoteParam.fromToken;
|
|
5835
|
-
const toToken = quote.quoteParam.toToken;
|
|
5836
6058
|
const depositAddress = quote.quote?.depositAddress;
|
|
5837
6059
|
const sendParam = quote.sendParam;
|
|
5838
6060
|
let _amountWei = quote.quoteParam?.amountWei;
|
|
@@ -5852,45 +6074,11 @@ var BridgeSFA = class {
|
|
|
5852
6074
|
csl("BridgeSFA.send", "blue-400", "sendParams: %o", sendParams);
|
|
5853
6075
|
const txhash = await service.send(sendParams);
|
|
5854
6076
|
try {
|
|
5855
|
-
const reportData = {
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
deposit_address: isOneClickService ? quote.quote?.depositAddress : "",
|
|
5861
|
-
receive_address: quote.quoteParam?.recipient,
|
|
5862
|
-
from_chain: fromToken.blockchain,
|
|
5863
|
-
symbol: /^USD₮0$/i.test(fromToken.symbol) ? "USDT" : fromToken.symbol,
|
|
5864
|
-
to_chain: toToken.blockchain,
|
|
5865
|
-
to_symbol: /^USD₮0$/i.test(toToken.symbol) ? "USDT" : toToken.symbol,
|
|
5866
|
-
tx_hash: ""
|
|
5867
|
-
};
|
|
5868
|
-
if (permitSignature) {
|
|
5869
|
-
if ([core.Service.OneClickUsdt0].includes(serviceType)) {
|
|
5870
|
-
reportData.layer_zero_permit = {
|
|
5871
|
-
...permitSignature,
|
|
5872
|
-
...quote.permitAdditionalData
|
|
5873
|
-
};
|
|
5874
|
-
}
|
|
5875
|
-
if ([core.Service.OneClickFraxZero, core.Service.FraxZeroOneClick].includes(serviceType)) {
|
|
5876
|
-
reportData.frax_zero_permit = {
|
|
5877
|
-
...permitSignature,
|
|
5878
|
-
...quote.permitAdditionalData
|
|
5879
|
-
};
|
|
5880
|
-
}
|
|
5881
|
-
}
|
|
5882
|
-
reportData.tx_hash = txhash;
|
|
5883
|
-
let _depositAddress = txhash;
|
|
5884
|
-
if (isQuoteParamDepositAddress) {
|
|
5885
|
-
_depositAddress = quote.quoteParam?.depositAddress || txhash;
|
|
5886
|
-
}
|
|
5887
|
-
if (!reportData.deposit_address) {
|
|
5888
|
-
reportData.deposit_address = _depositAddress;
|
|
5889
|
-
}
|
|
5890
|
-
if (serviceType === core.Service.Native) {
|
|
5891
|
-
const quoteIds = quote?.orders?.map?.((order) => order.quoteId) || [];
|
|
5892
|
-
reportData.quoteIds = quoteIds;
|
|
5893
|
-
}
|
|
6077
|
+
const reportData = _BridgeSFA.buildReportData(serviceType, {
|
|
6078
|
+
quote,
|
|
6079
|
+
txhash,
|
|
6080
|
+
permitSignature
|
|
6081
|
+
});
|
|
5894
6082
|
csl("BridgeSFA.send", "blue-400", "reportData: %o", reportData);
|
|
5895
6083
|
submitOthersTx(reportData);
|
|
5896
6084
|
} catch (error) {
|
|
@@ -5898,6 +6086,137 @@ var BridgeSFA = class {
|
|
|
5898
6086
|
}
|
|
5899
6087
|
return txhash;
|
|
5900
6088
|
}
|
|
6089
|
+
/**
|
|
6090
|
+
* Build the backend report payload for a submitted source-chain transaction.
|
|
6091
|
+
* Shared by `send` (fire-and-forget) and `report` (awaited).
|
|
6092
|
+
*/
|
|
6093
|
+
static buildReportData(serviceType, params) {
|
|
6094
|
+
const { quote, txhash, permitSignature } = params;
|
|
6095
|
+
const { isExactOutput, isOneClickService, isQuoteParamDepositAddress } = getQuoteModes({
|
|
6096
|
+
quoteData: quote,
|
|
6097
|
+
bridgeStore: { quoteDataService: serviceType }
|
|
6098
|
+
});
|
|
6099
|
+
const fromToken = quote.quoteParam.fromToken;
|
|
6100
|
+
const toToken = quote.quoteParam.toToken;
|
|
6101
|
+
let _amountWei = quote.quoteParam?.amountWei;
|
|
6102
|
+
if (isExactOutput) {
|
|
6103
|
+
_amountWei = quote.quote?.minAmountIn;
|
|
6104
|
+
}
|
|
6105
|
+
const reportData = {
|
|
6106
|
+
project: core.ServiceBackend[serviceType],
|
|
6107
|
+
address: quote.quoteParam?.refundTo,
|
|
6108
|
+
amount: isExactOutput ? quote.quote.amountInFormatted : Big__default.default(_amountWei || 0).div(10 ** (fromToken?.decimals || 6)).toFixed(fromToken?.decimals || 6, 0),
|
|
6109
|
+
out_amount: quote.outputAmount,
|
|
6110
|
+
deposit_address: isOneClickService ? quote.quote?.depositAddress : "",
|
|
6111
|
+
receive_address: quote.quoteParam?.recipient,
|
|
6112
|
+
from_chain: fromToken.blockchain,
|
|
6113
|
+
symbol: /^USD₮0$/i.test(fromToken.symbol) ? "USDT" : fromToken.symbol,
|
|
6114
|
+
to_chain: toToken.blockchain,
|
|
6115
|
+
to_symbol: /^USD₮0$/i.test(toToken.symbol) ? "USDT" : toToken.symbol,
|
|
6116
|
+
tx_hash: ""
|
|
6117
|
+
};
|
|
6118
|
+
if (permitSignature) {
|
|
6119
|
+
if ([core.Service.OneClickUsdt0].includes(serviceType)) {
|
|
6120
|
+
reportData.layer_zero_permit = {
|
|
6121
|
+
...permitSignature,
|
|
6122
|
+
...quote.permitAdditionalData
|
|
6123
|
+
};
|
|
6124
|
+
}
|
|
6125
|
+
if ([core.Service.OneClickFraxZero, core.Service.FraxZeroOneClick].includes(serviceType)) {
|
|
6126
|
+
reportData.frax_zero_permit = {
|
|
6127
|
+
...permitSignature,
|
|
6128
|
+
...quote.permitAdditionalData
|
|
6129
|
+
};
|
|
6130
|
+
}
|
|
6131
|
+
}
|
|
6132
|
+
reportData.tx_hash = txhash;
|
|
6133
|
+
let _depositAddress = txhash;
|
|
6134
|
+
if (isQuoteParamDepositAddress) {
|
|
6135
|
+
_depositAddress = quote.quoteParam?.depositAddress || txhash;
|
|
6136
|
+
}
|
|
6137
|
+
if (!reportData.deposit_address) {
|
|
6138
|
+
reportData.deposit_address = _depositAddress;
|
|
6139
|
+
}
|
|
6140
|
+
if (serviceType === core.Service.Native) {
|
|
6141
|
+
const quoteIds = quote?.orders?.map?.((order) => order.quoteId) || [];
|
|
6142
|
+
reportData.quoteIds = quoteIds;
|
|
6143
|
+
}
|
|
6144
|
+
return reportData;
|
|
6145
|
+
}
|
|
6146
|
+
/**
|
|
6147
|
+
* API-driven custody: build the serializable, unsigned transaction data for a
|
|
6148
|
+
* route WITHOUT a signer. Intended for MPC wallets (e.g. Fireblocks) that sign
|
|
6149
|
+
* and broadcast through their own infrastructure.
|
|
6150
|
+
*
|
|
6151
|
+
* Returns any required `approveTx` (and `approveResetTx` on Ethereum), the
|
|
6152
|
+
* `permitTypedData` to sign off-chain when `quote.needPermit`, and the main
|
|
6153
|
+
* `tx`. After the integrator broadcasts `tx`, call `BridgeSFA.report` with the
|
|
6154
|
+
* resulting hash (and the permit signature, if any) so StableFlow can execute
|
|
6155
|
+
* the destination leg.
|
|
6156
|
+
*
|
|
6157
|
+
* EVM only for now; non-EVM source chains throw.
|
|
6158
|
+
*/
|
|
6159
|
+
static async buildTransaction(serviceType, params) {
|
|
6160
|
+
const service = ServiceMap[serviceType];
|
|
6161
|
+
if (!service) {
|
|
6162
|
+
throw new Error(`Invalid service type: ${serviceType}`);
|
|
6163
|
+
}
|
|
6164
|
+
const { quote } = params;
|
|
6165
|
+
if (!quote) {
|
|
6166
|
+
throw new Error("Quote data is required");
|
|
6167
|
+
}
|
|
6168
|
+
const tx = buildSendTx(serviceType, quote);
|
|
6169
|
+
const { approveTx, approveResetTx } = buildApproveTx(serviceType, quote);
|
|
6170
|
+
const result = {
|
|
6171
|
+
chainId: tx.chainId,
|
|
6172
|
+
from: tx.from,
|
|
6173
|
+
tx
|
|
6174
|
+
};
|
|
6175
|
+
if (approveTx) {
|
|
6176
|
+
result.approveTx = approveTx;
|
|
6177
|
+
}
|
|
6178
|
+
if (approveResetTx) {
|
|
6179
|
+
result.approveResetTx = approveResetTx;
|
|
6180
|
+
}
|
|
6181
|
+
if (quote.needPermit) {
|
|
6182
|
+
result.permitTypedData = await buildPermitTypedData({
|
|
6183
|
+
permitToken: quote.permitToken,
|
|
6184
|
+
permitAmountWei: quote.permitAmountWei,
|
|
6185
|
+
permitSpender: quote.permitSpender,
|
|
6186
|
+
owner: quote.quoteParam?.evmAddress || quote.quoteParam?.refundTo
|
|
6187
|
+
});
|
|
6188
|
+
}
|
|
6189
|
+
return result;
|
|
6190
|
+
}
|
|
6191
|
+
/**
|
|
6192
|
+
* API-driven custody: report an externally signed & broadcast source-chain
|
|
6193
|
+
* transaction back to StableFlow so it can track and execute the destination
|
|
6194
|
+
* leg. Pair with `BridgeSFA.buildTransaction`.
|
|
6195
|
+
*
|
|
6196
|
+
* When `quote.needPermit === true`, `permitSignature` is required.
|
|
6197
|
+
*/
|
|
6198
|
+
static report(serviceType, params) {
|
|
6199
|
+
const service = ServiceMap[serviceType];
|
|
6200
|
+
if (!service) {
|
|
6201
|
+
throw new Error(`Invalid service type: ${serviceType}`);
|
|
6202
|
+
}
|
|
6203
|
+
const { quote, hash, permitSignature } = params;
|
|
6204
|
+
if (!quote) {
|
|
6205
|
+
throw new Error("Quote data is required");
|
|
6206
|
+
}
|
|
6207
|
+
if (!hash) {
|
|
6208
|
+
throw new Error("Transaction hash is required");
|
|
6209
|
+
}
|
|
6210
|
+
if (quote.needPermit && !permitSignature) {
|
|
6211
|
+
throw new Error("Permit signature is required");
|
|
6212
|
+
}
|
|
6213
|
+
const reportData = _BridgeSFA.buildReportData(serviceType, {
|
|
6214
|
+
quote,
|
|
6215
|
+
txhash: hash,
|
|
6216
|
+
permitSignature
|
|
6217
|
+
});
|
|
6218
|
+
return submitOthersTx(reportData);
|
|
6219
|
+
}
|
|
5901
6220
|
static async getStatus(serviceType, params) {
|
|
5902
6221
|
const cs = new core.Csl(core.OpenAPI.DEBUG);
|
|
5903
6222
|
const csl = cs.log;
|
|
@@ -6016,6 +6335,9 @@ exports.ServiceMap = ServiceMap;
|
|
|
6016
6335
|
exports.USDT0_CONFIG = USDT0_CONFIG;
|
|
6017
6336
|
exports.USDT0_LEGACY_MESH_TRANSFTER_FEE = USDT0_LEGACY_MESH_TRANSFTER_FEE;
|
|
6018
6337
|
exports.addressToBytes32 = addressToBytes32;
|
|
6338
|
+
exports.buildApproveTx = buildApproveTx;
|
|
6339
|
+
exports.buildPermitTypedData = buildPermitTypedData;
|
|
6340
|
+
exports.buildSendTx = buildSendTx;
|
|
6019
6341
|
exports.formatNumber = formatNumber;
|
|
6020
6342
|
exports.formatQuoteError = formatQuoteError;
|
|
6021
6343
|
exports.getHopMsgFee = getHopMsgFee;
|