omnipin 3.0.0 → 3.0.1
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.js +330 -88
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9712,7 +9712,7 @@ let createUploadPiecesPayload_metadata = [
|
|
|
9712
9712
|
filecoinMainnet.id, filecoinCalibration.id;
|
|
9713
9713
|
let SIZE_CONSTANTS = {
|
|
9714
9714
|
TiB: 1n << 40n
|
|
9715
|
-
}, LOCKUP_PERIOD = 30n * 2880n, getClientDatasets_abi = {
|
|
9715
|
+
}, LOCKUP_PERIOD = 30n * 2880n, DEFAULT_MINIMUM_NEW_DATASET_LOCKUP = 60000000000000000n * LOCKUP_PERIOD / 86400n + 100000000000000000n, getClientDatasets_abi = {
|
|
9716
9716
|
type: 'function',
|
|
9717
9717
|
name: 'getClientDataSets',
|
|
9718
9718
|
inputs: [
|
|
@@ -12713,7 +12713,7 @@ let serializedType = '0x02', TxEnvelopeEip1559_type = 'eip1559', SIMULATION_GAS_
|
|
|
12713
12713
|
}
|
|
12714
12714
|
attempt < maxAttempts && await promises_setTimeout(intervalMs);
|
|
12715
12715
|
}
|
|
12716
|
-
throw Error(`Squid bridge poll timed out after ${maxAttempts} attempts
|
|
12716
|
+
throw Error(`Squid bridge poll timed out after ${maxAttempts} attempts; it may still complete — track: https://axelarscan.io/gmp/${transactionId}`);
|
|
12717
12717
|
}, getRouteWithRetry = async ({ params, attempts = 3, initialDelayMs = 5000, fetchFn = fetch, integratorId = getIntegratorId() })=>{
|
|
12718
12718
|
let lastErr;
|
|
12719
12719
|
for(let i = 0; i < attempts; i++)try {
|
|
@@ -12731,7 +12731,7 @@ let serializedType = '0x02', TxEnvelopeEip1559_type = 'eip1559', SIMULATION_GAS_
|
|
|
12731
12731
|
throw e;
|
|
12732
12732
|
}
|
|
12733
12733
|
throw lastErr instanceof Error ? lastErr : Error('Squid retry exhausted');
|
|
12734
|
-
}, filecoin_bridge_SOURCE_CHAINS = {
|
|
12734
|
+
}, FILECOIN_MAINNET_explorer = 'https://filfox.info/en', PERMIT2_ADDRESS = '0x000000000022D473030F116dDEE9F6B43aC78BA3', MAX_UINT160 = 2n ** 160n - 1n, MAX_UINT48 = 281474976710656 - 1, filecoin_bridge_MAX_UINT256 = 2n ** 256n - 1n, filecoin_bridge_SOURCE_CHAINS = {
|
|
12735
12735
|
eth: {
|
|
12736
12736
|
id: 1,
|
|
12737
12737
|
name: 'Ethereum',
|
|
@@ -12867,6 +12867,76 @@ let serializedType = '0x02', TxEnvelopeEip1559_type = 'eip1559', SIMULATION_GAS_
|
|
|
12867
12867
|
type: 'uint8'
|
|
12868
12868
|
}
|
|
12869
12869
|
]
|
|
12870
|
+
}, erc20BalanceOf = {
|
|
12871
|
+
name: 'balanceOf',
|
|
12872
|
+
type: 'function',
|
|
12873
|
+
stateMutability: 'view',
|
|
12874
|
+
inputs: [
|
|
12875
|
+
{
|
|
12876
|
+
name: 'account',
|
|
12877
|
+
type: 'address'
|
|
12878
|
+
}
|
|
12879
|
+
],
|
|
12880
|
+
outputs: [
|
|
12881
|
+
{
|
|
12882
|
+
type: 'uint256'
|
|
12883
|
+
}
|
|
12884
|
+
]
|
|
12885
|
+
}, permit2Approve = {
|
|
12886
|
+
name: 'approve',
|
|
12887
|
+
type: 'function',
|
|
12888
|
+
stateMutability: 'nonpayable',
|
|
12889
|
+
inputs: [
|
|
12890
|
+
{
|
|
12891
|
+
name: 'token',
|
|
12892
|
+
type: 'address'
|
|
12893
|
+
},
|
|
12894
|
+
{
|
|
12895
|
+
name: 'spender',
|
|
12896
|
+
type: 'address'
|
|
12897
|
+
},
|
|
12898
|
+
{
|
|
12899
|
+
name: 'amount',
|
|
12900
|
+
type: 'uint160'
|
|
12901
|
+
},
|
|
12902
|
+
{
|
|
12903
|
+
name: 'expiration',
|
|
12904
|
+
type: 'uint48'
|
|
12905
|
+
}
|
|
12906
|
+
],
|
|
12907
|
+
outputs: []
|
|
12908
|
+
}, permit2Allowance = {
|
|
12909
|
+
name: 'allowance',
|
|
12910
|
+
type: 'function',
|
|
12911
|
+
stateMutability: 'view',
|
|
12912
|
+
inputs: [
|
|
12913
|
+
{
|
|
12914
|
+
name: 'owner',
|
|
12915
|
+
type: 'address'
|
|
12916
|
+
},
|
|
12917
|
+
{
|
|
12918
|
+
name: 'token',
|
|
12919
|
+
type: 'address'
|
|
12920
|
+
},
|
|
12921
|
+
{
|
|
12922
|
+
name: 'spender',
|
|
12923
|
+
type: 'address'
|
|
12924
|
+
}
|
|
12925
|
+
],
|
|
12926
|
+
outputs: [
|
|
12927
|
+
{
|
|
12928
|
+
name: 'amount',
|
|
12929
|
+
type: 'uint160'
|
|
12930
|
+
},
|
|
12931
|
+
{
|
|
12932
|
+
name: 'expiration',
|
|
12933
|
+
type: 'uint48'
|
|
12934
|
+
},
|
|
12935
|
+
{
|
|
12936
|
+
name: 'nonce',
|
|
12937
|
+
type: 'uint48'
|
|
12938
|
+
}
|
|
12939
|
+
]
|
|
12870
12940
|
}, fetchTokenDecimals = async ({ provider, token })=>token.toLowerCase() === NATIVE_TOKEN.toLowerCase() ? 18 : Number(toBigInt(await provider.request({
|
|
12871
12941
|
method: 'eth_call',
|
|
12872
12942
|
params: [
|
|
@@ -12876,8 +12946,21 @@ let serializedType = '0x02', TxEnvelopeEip1559_type = 'eip1559', SIMULATION_GAS_
|
|
|
12876
12946
|
},
|
|
12877
12947
|
'latest'
|
|
12878
12948
|
]
|
|
12879
|
-
}))),
|
|
12880
|
-
|
|
12949
|
+
}))), fetchSourceBalance = async ({ provider, token, owner })=>token.toLowerCase() === NATIVE_TOKEN.toLowerCase() ? getBalance({
|
|
12950
|
+
provider,
|
|
12951
|
+
address: owner
|
|
12952
|
+
}) : toBigInt(await provider.request({
|
|
12953
|
+
method: 'eth_call',
|
|
12954
|
+
params: [
|
|
12955
|
+
{
|
|
12956
|
+
to: token,
|
|
12957
|
+
data: AbiFunction_encodeData(erc20BalanceOf, [
|
|
12958
|
+
owner
|
|
12959
|
+
])
|
|
12960
|
+
},
|
|
12961
|
+
'latest'
|
|
12962
|
+
]
|
|
12963
|
+
})), readErc20Allowance = async ({ provider, token, owner, spender })=>toBigInt(await provider.request({
|
|
12881
12964
|
method: 'eth_call',
|
|
12882
12965
|
params: [
|
|
12883
12966
|
{
|
|
@@ -12889,26 +12972,162 @@ let serializedType = '0x02', TxEnvelopeEip1559_type = 'eip1559', SIMULATION_GAS_
|
|
|
12889
12972
|
},
|
|
12890
12973
|
'latest'
|
|
12891
12974
|
]
|
|
12892
|
-
}))
|
|
12893
|
-
|
|
12894
|
-
|
|
12895
|
-
|
|
12896
|
-
|
|
12897
|
-
|
|
12975
|
+
})), readPermit2Allowance = async ({ provider, token, owner, spender })=>{
|
|
12976
|
+
let raw = await provider.request({
|
|
12977
|
+
method: 'eth_call',
|
|
12978
|
+
params: [
|
|
12979
|
+
{
|
|
12980
|
+
to: PERMIT2_ADDRESS,
|
|
12981
|
+
data: AbiFunction_encodeData(permit2Allowance, [
|
|
12982
|
+
owner,
|
|
12983
|
+
token,
|
|
12984
|
+
spender
|
|
12985
|
+
])
|
|
12986
|
+
},
|
|
12987
|
+
'latest'
|
|
12988
|
+
]
|
|
12989
|
+
}), [amount, expiration] = AbiFunction_decodeResult(permit2Allowance, raw);
|
|
12990
|
+
return {
|
|
12991
|
+
amount,
|
|
12992
|
+
expiration
|
|
12993
|
+
};
|
|
12994
|
+
}, ensureRouterAllowances = async ({ provider, privateKey, owner, token, spender, amount, chainId })=>{
|
|
12995
|
+
if (await readErc20Allowance({
|
|
12898
12996
|
provider,
|
|
12899
|
-
|
|
12900
|
-
|
|
12901
|
-
|
|
12902
|
-
|
|
12903
|
-
|
|
12997
|
+
token,
|
|
12998
|
+
owner,
|
|
12999
|
+
spender
|
|
13000
|
+
}) < amount) {
|
|
13001
|
+
logger.info('Approving the router to spend the source token');
|
|
13002
|
+
let txHash = await sendTransaction({
|
|
13003
|
+
provider,
|
|
13004
|
+
chainId,
|
|
13005
|
+
privateKey,
|
|
13006
|
+
to: token,
|
|
13007
|
+
data: AbiFunction_encodeData(erc20Approve, [
|
|
13008
|
+
spender,
|
|
13009
|
+
filecoin_bridge_MAX_UINT256
|
|
13010
|
+
]),
|
|
13011
|
+
from: owner
|
|
13012
|
+
});
|
|
13013
|
+
await waitForTransaction(provider, txHash);
|
|
13014
|
+
}
|
|
13015
|
+
if (await readErc20Allowance({
|
|
13016
|
+
provider,
|
|
13017
|
+
token,
|
|
13018
|
+
owner,
|
|
13019
|
+
spender: PERMIT2_ADDRESS
|
|
13020
|
+
}) < amount) {
|
|
13021
|
+
logger.info('Approving Permit2 to spend the source token');
|
|
13022
|
+
let txHash = await sendTransaction({
|
|
13023
|
+
provider,
|
|
13024
|
+
chainId,
|
|
13025
|
+
privateKey,
|
|
13026
|
+
to: token,
|
|
13027
|
+
data: AbiFunction_encodeData(erc20Approve, [
|
|
13028
|
+
PERMIT2_ADDRESS,
|
|
13029
|
+
filecoin_bridge_MAX_UINT256
|
|
13030
|
+
]),
|
|
13031
|
+
from: owner
|
|
13032
|
+
});
|
|
13033
|
+
await waitForTransaction(provider, txHash);
|
|
13034
|
+
}
|
|
13035
|
+
let nowSeconds = Math.floor(Date.now() / 1000), permit2 = await readPermit2Allowance({
|
|
13036
|
+
provider,
|
|
13037
|
+
token,
|
|
13038
|
+
owner,
|
|
13039
|
+
spender
|
|
12904
13040
|
});
|
|
12905
|
-
|
|
13041
|
+
if (permit2.amount < amount || permit2.expiration <= nowSeconds) {
|
|
13042
|
+
logger.info(`Authorizing ${spender} to spend via Permit2`);
|
|
13043
|
+
let txHash = await sendTransaction({
|
|
13044
|
+
provider,
|
|
13045
|
+
chainId,
|
|
13046
|
+
privateKey,
|
|
13047
|
+
to: PERMIT2_ADDRESS,
|
|
13048
|
+
data: AbiFunction_encodeData(permit2Approve, [
|
|
13049
|
+
token,
|
|
13050
|
+
spender,
|
|
13051
|
+
MAX_UINT160,
|
|
13052
|
+
MAX_UINT48
|
|
13053
|
+
]),
|
|
13054
|
+
from: owner
|
|
13055
|
+
});
|
|
13056
|
+
await waitForTransaction(provider, txHash);
|
|
13057
|
+
}
|
|
13058
|
+
}, SOURCE_FINALITY_MS = {
|
|
13059
|
+
eth: 900000
|
|
13060
|
+
}, withFinalityCountdown = async ({ chain, label, verbose }, task)=>{
|
|
13061
|
+
let finalityMs = SOURCE_FINALITY_MS[chain];
|
|
13062
|
+
if (!finalityMs || verbose) return task();
|
|
13063
|
+
if (!process.stdout.isTTY) return logger.info(`${label} leg: waiting ~${Math.round(finalityMs / 60000)} min for source-chain finality…`), task();
|
|
13064
|
+
let startedAt = Date.now(), render = ()=>{
|
|
13065
|
+
let totalSeconds, minutes, remaining = finalityMs - (Date.now() - startedAt), line = remaining > 0 ? `⏳ ${label} leg: waiting for finality… ${minutes = Math.floor((totalSeconds = Math.max(0, Math.ceil(remaining / 1000))) / 60), `${minutes}:${(totalSeconds % 60).toString().padStart(2, '0')}`} remaining` : `⏳ ${label} leg: finalized; waiting for relayer… ${Math.round(-remaining / 1000)}s`;
|
|
13066
|
+
process.stdout.cursorTo(0), process.stdout.write(line), process.stdout.clearLine(1);
|
|
13067
|
+
};
|
|
13068
|
+
render();
|
|
13069
|
+
let timer = setInterval(render, 1000);
|
|
13070
|
+
try {
|
|
13071
|
+
return await task();
|
|
13072
|
+
} finally{
|
|
13073
|
+
clearInterval(timer), process.stdout.cursorTo(0), process.stdout.clearLine(0);
|
|
13074
|
+
}
|
|
13075
|
+
}, fwssMinimumDeposit = async ()=>{
|
|
13076
|
+
try {
|
|
13077
|
+
let minimumPricePerMonth, epochsPerMonth, pricing = await getServicePricing({
|
|
13078
|
+
chain: filecoinMainnet
|
|
13079
|
+
});
|
|
13080
|
+
return minimumPricePerMonth = pricing.minimumPricePerMonth, epochsPerMonth = pricing.epochsPerMonth, minimumPricePerMonth * LOCKUP_PERIOD / epochsPerMonth + 100000000000000000n;
|
|
13081
|
+
} catch {
|
|
13082
|
+
return DEFAULT_MINIMUM_NEW_DATASET_LOCKUP;
|
|
13083
|
+
}
|
|
13084
|
+
}, applyRatio = (amount, ratio)=>amount * BigInt(Math.round(1000000 * ratio)) / 1000000n, filToUsdfcParams = ({ signer, amount, slippage })=>({
|
|
13085
|
+
fromAddress: signer,
|
|
13086
|
+
fromChain: String(314),
|
|
13087
|
+
fromToken: NATIVE_TOKEN,
|
|
13088
|
+
fromAmount: amount.toString(),
|
|
13089
|
+
toChain: String(314),
|
|
13090
|
+
toToken: '0x80b98d3aa09ffff255c3ba4a241111ff1262f045',
|
|
13091
|
+
toAddress: signer,
|
|
13092
|
+
slippage
|
|
13093
|
+
}), assertClearsFwssFloor = async (route)=>{
|
|
13094
|
+
let floor = await fwssMinimumDeposit(), out = BigInt(route.estimate.toAmountMin ?? route.estimate.toAmount ?? '0');
|
|
13095
|
+
if (out < floor) throw Error(`The USDfc portion would deliver ~${Value_format(out, 18)} USDfc, below Filecoin Pay's minimum deposit of ${Value_format(floor, 18)} USDfc. Bridge a larger amount (or lower --fil-ratio) so the storage portion clears the floor.`);
|
|
13096
|
+
}, waitForFilCredit = async ({ provider, address, baseline, maxAttempts = 30, intervalMs = 10000, verbose })=>{
|
|
13097
|
+
for(let i = 0; i < maxAttempts; i++){
|
|
13098
|
+
let balance = await getBalance({
|
|
13099
|
+
provider,
|
|
13100
|
+
address
|
|
13101
|
+
});
|
|
13102
|
+
if (balance > baseline) return balance - baseline;
|
|
13103
|
+
verbose && i % 3 == 0 && logger.info(`Waiting for bridged FIL to land on Filecoin… (poll ${i + 1})`), await promises_setTimeout(intervalMs);
|
|
13104
|
+
}
|
|
13105
|
+
throw Error('Bridged FIL did not appear on Filecoin within the expected window. It may still arrive — check your wallet before retrying.');
|
|
13106
|
+
}, estimateFilSwapGas = async ({ provider, signer, route })=>{
|
|
13107
|
+
let tx = route.transactionRequest, gasLimit = tx.gasLimit ? BigInt(tx.gasLimit) : await estimateGas({
|
|
13108
|
+
provider,
|
|
13109
|
+
to: tx.target,
|
|
13110
|
+
data: tx.data,
|
|
13111
|
+
from: signer,
|
|
13112
|
+
value: tx.value ? fromNumber(BigInt(tx.value)) : '0x0'
|
|
13113
|
+
}), block = await provider.request({
|
|
13114
|
+
method: 'eth_getBlockByNumber',
|
|
13115
|
+
params: [
|
|
13116
|
+
'latest',
|
|
13117
|
+
!1
|
|
13118
|
+
]
|
|
13119
|
+
});
|
|
13120
|
+
return gasLimit * (2n * toBigInt(block?.baseFeePerGas ?? '0x0') + toBigInt(await provider.request({
|
|
13121
|
+
method: 'eth_maxPriorityFeePerGas'
|
|
13122
|
+
}))) * 12n / 10n;
|
|
12906
13123
|
}, bridgeFilecoin = async ({ privateKey, fromChain, fromToken, amount, to, filRatio, slippage, sourceRpcUrl, verbose })=>{
|
|
12907
13124
|
let totalAmountAtomic;
|
|
12908
13125
|
if (filRatio < 0 || filRatio > 1) throw Error(`--fil-ratio must be in [0, 1], got ${filRatio}`);
|
|
12909
13126
|
let signer = fromPublicKey(Secp256k1_getPublicKey({
|
|
12910
13127
|
privateKey
|
|
12911
|
-
}))
|
|
13128
|
+
}));
|
|
13129
|
+
if ((to ?? signer).toLowerCase() !== signer.toLowerCase()) throw Error('Bridging to Filecoin lands native FIL in your wallet and swaps part of it to USDfc on Filecoin, which must be signed from the receiving wallet. Omit --to (or set it to your own address); bridging to a different address is not supported for this flow.');
|
|
13130
|
+
let chainConfig = filecoin_bridge_SOURCE_CHAINS[fromChain], sourceToken = (({ chain, token })=>{
|
|
12912
13131
|
if (token.startsWith('0x') && 42 === token.length) return token;
|
|
12913
13132
|
let upper = token.toUpperCase(), chainConfig = filecoin_bridge_SOURCE_CHAINS[chain];
|
|
12914
13133
|
for (let [sym, addr] of Object.entries(chainConfig.tokens))if (sym.toUpperCase() === upper) return addr;
|
|
@@ -12926,87 +13145,108 @@ let serializedType = '0x02', TxEnvelopeEip1559_type = 'eip1559', SIMULATION_GAS_
|
|
|
12926
13145
|
throw Error(`Invalid amount: ${amount}`);
|
|
12927
13146
|
}
|
|
12928
13147
|
if (totalAmountAtomic <= 0n) throw Error(`Amount must be positive: ${amount}`);
|
|
12929
|
-
|
|
12930
|
-
|
|
12931
|
-
|
|
13148
|
+
if (logger.start(`Bridge to Filecoin: ${amount} ${fromToken} from ${chainConfig.name}`), await fetchSourceBalance({
|
|
13149
|
+
provider,
|
|
13150
|
+
token: sourceToken,
|
|
13151
|
+
owner: signer
|
|
13152
|
+
}) < totalAmountAtomic) throw Error(`Insufficient ${fromToken} on ${chainConfig.name}`);
|
|
13153
|
+
let bridgeParams = {
|
|
12932
13154
|
fromAddress: signer,
|
|
12933
13155
|
fromChain: String(chainConfig.id),
|
|
12934
13156
|
fromToken: sourceToken,
|
|
12935
|
-
fromAmount:
|
|
13157
|
+
fromAmount: totalAmountAtomic.toString(),
|
|
12936
13158
|
toChain: String(314),
|
|
12937
13159
|
toToken: NATIVE_TOKEN,
|
|
12938
|
-
toAddress:
|
|
13160
|
+
toAddress: signer,
|
|
12939
13161
|
slippage
|
|
12940
|
-
}
|
|
12941
|
-
|
|
12942
|
-
|
|
12943
|
-
|
|
12944
|
-
|
|
12945
|
-
|
|
12946
|
-
|
|
12947
|
-
toAddress: destination,
|
|
12948
|
-
slippage
|
|
12949
|
-
} : void 0, filRoute = filParams ? await getRouteWithRetry({
|
|
12950
|
-
params: filParams
|
|
12951
|
-
}) : void 0, usdfcRoute = usdfcParams ? await getRouteWithRetry({
|
|
12952
|
-
params: usdfcParams
|
|
12953
|
-
}) : void 0;
|
|
12954
|
-
if (verbose && (filRoute && logRouteSummary('FIL', filRoute), usdfcRoute && logRouteSummary('USDfc', usdfcRoute)), sourceToken.toLowerCase() !== NATIVE_TOKEN.toLowerCase()) {
|
|
12955
|
-
let spender = filRoute?.transactionRequest.target ?? usdfcRoute?.transactionRequest.target;
|
|
12956
|
-
await ensureAllowance({
|
|
12957
|
-
provider,
|
|
12958
|
-
privateKey,
|
|
12959
|
-
owner: signer,
|
|
12960
|
-
token: sourceToken,
|
|
12961
|
-
spender,
|
|
12962
|
-
amount: totalAmountAtomic,
|
|
12963
|
-
chainId: chainConfig.id
|
|
12964
|
-
});
|
|
12965
|
-
}
|
|
12966
|
-
let result = {};
|
|
12967
|
-
if (filRoute && filParams) {
|
|
12968
|
-
logger.info(`Executing FIL leg on ${chainConfig.name}`);
|
|
12969
|
-
let txHash = await executeRoute({
|
|
12970
|
-
provider,
|
|
12971
|
-
privateKey,
|
|
12972
|
-
chainId: chainConfig.id,
|
|
13162
|
+
}, bridgeRoute = await getRouteWithRetry({
|
|
13163
|
+
params: bridgeParams
|
|
13164
|
+
});
|
|
13165
|
+
verbose && logRouteSummary('bridge→FIL', bridgeRoute);
|
|
13166
|
+
let preflightSwapIn = applyRatio(BigInt(bridgeRoute.estimate.toAmountMin ?? bridgeRoute.estimate.toAmount ?? '0'), 1 - filRatio);
|
|
13167
|
+
preflightSwapIn > 0n && await assertClearsFwssFloor(await getRouteWithRetry({
|
|
13168
|
+
params: filToUsdfcParams({
|
|
12973
13169
|
signer,
|
|
12974
|
-
|
|
12975
|
-
|
|
12976
|
-
|
|
12977
|
-
|
|
12978
|
-
|
|
12979
|
-
|
|
13170
|
+
amount: preflightSwapIn,
|
|
13171
|
+
slippage
|
|
13172
|
+
})
|
|
13173
|
+
})), sourceToken.toLowerCase() !== NATIVE_TOKEN.toLowerCase() && await ensureRouterAllowances({
|
|
13174
|
+
provider,
|
|
13175
|
+
privateKey,
|
|
13176
|
+
owner: signer,
|
|
13177
|
+
token: sourceToken,
|
|
13178
|
+
spender: bridgeRoute.transactionRequest.target,
|
|
13179
|
+
amount: totalAmountAtomic,
|
|
13180
|
+
chainId: chainConfig.id
|
|
13181
|
+
});
|
|
13182
|
+
let result = {}, fil = constants_filProvider[filecoinMainnet.id], filBefore = await getBalance({
|
|
13183
|
+
provider: fil,
|
|
13184
|
+
address: signer
|
|
13185
|
+
});
|
|
13186
|
+
logger.info(`Executing bridge on ${chainConfig.name}`);
|
|
13187
|
+
let bridgeTxHash = await executeRoute({
|
|
13188
|
+
provider,
|
|
13189
|
+
privateKey,
|
|
13190
|
+
chainId: chainConfig.id,
|
|
13191
|
+
signer,
|
|
13192
|
+
route: bridgeRoute
|
|
13193
|
+
});
|
|
13194
|
+
logger.info(`Bridge tx: ${chainConfig.explorer}/tx/${bridgeTxHash}`), await waitForTransaction(provider, bridgeTxHash), logger.info('Bridge source tx confirmed; polling relayer…'), logger.info(`Track: https://axelarscan.io/gmp/${bridgeTxHash}`), result.bridgeStatus = await withFinalityCountdown({
|
|
13195
|
+
chain: fromChain,
|
|
13196
|
+
label: 'bridge',
|
|
13197
|
+
verbose
|
|
13198
|
+
}, ()=>pollSquidStatus({
|
|
13199
|
+
transactionId: bridgeTxHash,
|
|
13200
|
+
requestId: bridgeRoute.params?.requestId,
|
|
12980
13201
|
fromChainId: String(chainConfig.id),
|
|
12981
13202
|
toChainId: String(314),
|
|
13203
|
+
maxAttempts: 120,
|
|
13204
|
+
intervalMs: 15000,
|
|
12982
13205
|
onAttempt: (n, s)=>{
|
|
12983
|
-
verbose && logger.info(`
|
|
13206
|
+
verbose && logger.info(` bridge poll #${n}: status=${s ?? '<none>'}`);
|
|
12984
13207
|
}
|
|
12985
|
-
});
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
12990
|
-
|
|
12991
|
-
|
|
12992
|
-
|
|
12993
|
-
|
|
13208
|
+
})), result.bridgeTxHash = bridgeTxHash, logger.success('Bridged to native FIL');
|
|
13209
|
+
let bridgedFil = await waitForFilCredit({
|
|
13210
|
+
provider: fil,
|
|
13211
|
+
address: signer,
|
|
13212
|
+
baseline: filBefore,
|
|
13213
|
+
verbose
|
|
13214
|
+
});
|
|
13215
|
+
result.bridgedFil = Value_format(bridgedFil, 18), logger.info(`Received ${Value_format(bridgedFil, 18)} FIL`);
|
|
13216
|
+
let swapIn = applyRatio(bridgedFil, 1 - filRatio), keptFil = bridgedFil - swapIn;
|
|
13217
|
+
if (swapIn <= 0n) return logger.warn('--fil-ratio leaves nothing to swap; keeping all FIL'), result.keptFil = Value_format(bridgedFil, 18), logger.success('Filecoin bridge complete'), result;
|
|
13218
|
+
let swapRoute = await getRouteWithRetry({
|
|
13219
|
+
params: filToUsdfcParams({
|
|
12994
13220
|
signer,
|
|
12995
|
-
|
|
12996
|
-
|
|
12997
|
-
|
|
12998
|
-
|
|
12999
|
-
|
|
13000
|
-
|
|
13001
|
-
|
|
13002
|
-
|
|
13003
|
-
|
|
13004
|
-
|
|
13005
|
-
|
|
13221
|
+
amount: swapIn,
|
|
13222
|
+
slippage
|
|
13223
|
+
})
|
|
13224
|
+
}), gasReserve = await estimateFilSwapGas({
|
|
13225
|
+
provider: fil,
|
|
13226
|
+
signer,
|
|
13227
|
+
route: swapRoute
|
|
13228
|
+
});
|
|
13229
|
+
if (keptFil < gasReserve) {
|
|
13230
|
+
if (bridgedFil <= gasReserve) throw Error(`Received FIL (${Value_format(bridgedFil, 18)}) can't cover the on-chain swap gas (~${Value_format(gasReserve, 18)} FIL). Bridge a larger amount.`);
|
|
13231
|
+
swapIn = bridgedFil - gasReserve, keptFil = gasReserve, swapRoute = await getRouteWithRetry({
|
|
13232
|
+
params: filToUsdfcParams({
|
|
13233
|
+
signer,
|
|
13234
|
+
amount: swapIn,
|
|
13235
|
+
slippage
|
|
13236
|
+
})
|
|
13006
13237
|
});
|
|
13007
|
-
logger.success('USDfc leg bridged'), result.usdfcTxHash = txHash, result.usdfcStatus = status;
|
|
13008
13238
|
}
|
|
13009
|
-
|
|
13239
|
+
verbose && logRouteSummary('FIL→USDfc', swapRoute);
|
|
13240
|
+
let expectedUsdfc = BigInt(swapRoute.estimate.toAmountMin ?? swapRoute.estimate.toAmount ?? '0'), floor = await fwssMinimumDeposit();
|
|
13241
|
+
expectedUsdfc < floor && logger.warn(`Swap will yield ~${Value_format(expectedUsdfc, 18)} USDfc, below Filecoin Pay's ${Value_format(floor, 18)} USDfc minimum deposit. Proceeding — top up before depositing for storage.`), logger.info(`Swapping ${Value_format(swapIn, 18)} FIL → USDfc on Filecoin (keeping ${Value_format(keptFil, 18)} FIL for gas)`);
|
|
13242
|
+
let swapTxHash = await executeRoute({
|
|
13243
|
+
provider: fil,
|
|
13244
|
+
privateKey,
|
|
13245
|
+
chainId: filecoinMainnet.id,
|
|
13246
|
+
signer,
|
|
13247
|
+
route: swapRoute
|
|
13248
|
+
});
|
|
13249
|
+
return logger.info(`Swap tx: ${FILECOIN_MAINNET_explorer}/tx/${swapTxHash}`), await waitForTransaction(fil, swapTxHash), logger.success('Swapped FIL → USDfc on Filecoin'), result.swapTxHash = swapTxHash, result.keptFil = Value_format(keptFil, 18), result.usdfcExpected = Value_format(expectedUsdfc, 18), logger.success('Filecoin bridge complete'), result;
|
|
13010
13250
|
}, executeRoute = async ({ provider, privateKey, chainId, signer, route })=>{
|
|
13011
13251
|
let tx = route.transactionRequest, value = tx.value ? BigInt(tx.value) : 0n;
|
|
13012
13252
|
return await sendTransaction({
|
|
@@ -13100,6 +13340,8 @@ let serializedType = '0x02', TxEnvelopeEip1559_type = 'eip1559', SIMULATION_GAS_
|
|
|
13100
13340
|
return providers;
|
|
13101
13341
|
}, findEnvVarProviderName = (provider)=>{
|
|
13102
13342
|
for (let [token, { name }] of Object.entries(PROVIDERS))if (provider === name) return token;
|
|
13343
|
+
let known = Object.values(PROVIDERS).map((p)=>p.name).join(', ');
|
|
13344
|
+
throw Error(`Unknown provider: '${provider}'. Known providers: ${known}`);
|
|
13103
13345
|
}, updateDnsLink = async ({ cid, zoneId, apiKey, name, verbose })=>{
|
|
13104
13346
|
let res = await fetch(`${CLOUDFLARE_API_URL}/zones/${zoneId}/web3/hostnames`, {
|
|
13105
13347
|
headers: {
|
|
@@ -17653,7 +17895,7 @@ let picomatch = __webpack_require__("./node_modules/picomatch/index.js"), isRead
|
|
|
17653
17895
|
chainId: filecoinMainnet.id,
|
|
17654
17896
|
privateKey
|
|
17655
17897
|
});
|
|
17656
|
-
return logger.info(`Deposit tx:
|
|
17898
|
+
return logger.info(`Deposit tx: ${FILECOIN_MAINNET_explorer}/tx/${depositHash}`), await waitForTransaction(constants_filProvider[filecoinMainnet.id], depositHash), logger.success('Deposit confirmed'), {
|
|
17657
17899
|
depositTxHash: depositHash,
|
|
17658
17900
|
depositedAmount: amountAtomic
|
|
17659
17901
|
};
|
|
@@ -18185,7 +18427,7 @@ cli_cli.command('deploy', ([dir], options)=>deployAction({
|
|
|
18185
18427
|
},
|
|
18186
18428
|
{
|
|
18187
18429
|
name: 'to',
|
|
18188
|
-
description: 'Destination address on the provider chain. Defaults to the signer address.',
|
|
18430
|
+
description: 'Destination address on the provider chain. Defaults to the signer address. For Filecoin it must be the signer (the destination swap is signed locally).',
|
|
18189
18431
|
type: 'string'
|
|
18190
18432
|
},
|
|
18191
18433
|
{
|
|
@@ -18200,7 +18442,7 @@ cli_cli.command('deploy', ([dir], options)=>deployAction({
|
|
|
18200
18442
|
},
|
|
18201
18443
|
{
|
|
18202
18444
|
name: 'fil-ratio',
|
|
18203
|
-
description: 'Fraction of the
|
|
18445
|
+
description: 'Fraction of the bridged FIL kept for gas; the rest is swapped to USDfc on Filecoin. Filecoin only. Default 0.1.',
|
|
18204
18446
|
type: 'string'
|
|
18205
18447
|
},
|
|
18206
18448
|
{
|