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.
Files changed (2) hide show
  1. package/dist/index.js +330 -88
  2. 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 for tx ${transactionId}`);
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
- }))), ensureAllowance = async ({ provider, privateKey, owner, token, spender, amount, chainId })=>{
12880
- if (toBigInt(await provider.request({
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
- })) >= amount) return;
12893
- logger.info(`Approving ${spender} to spend the source token`);
12894
- let data = AbiFunction_encodeData(erc20Approve, [
12895
- spender,
12896
- 2n ** 256n - 1n
12897
- ]), txHash = await sendTransaction({
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
- chainId,
12900
- privateKey,
12901
- to: token,
12902
- data,
12903
- from: owner
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
- await waitForTransaction(provider, txHash);
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
- })), destination = to ?? signer, chainConfig = filecoin_bridge_SOURCE_CHAINS[fromChain], sourceToken = (({ chain, token })=>{
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
- let filAtomic = totalAmountAtomic * BigInt(Math.round(1000000 * filRatio)) / 1000000n, usdfcAtomic = totalAmountAtomic - filAtomic;
12930
- logger.start(`Bridge to Filecoin: ${amount} ${fromToken} from ${chainConfig.name} → ${destination}`), logger.info(`Split: ${filAtomic} (FIL leg) + ${usdfcAtomic} (USDfc leg), source-token atomic units`);
12931
- let filParams = filAtomic > 0n ? {
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: filAtomic.toString(),
13157
+ fromAmount: totalAmountAtomic.toString(),
12936
13158
  toChain: String(314),
12937
13159
  toToken: NATIVE_TOKEN,
12938
- toAddress: destination,
13160
+ toAddress: signer,
12939
13161
  slippage
12940
- } : void 0, usdfcParams = usdfcAtomic > 0n ? {
12941
- fromAddress: signer,
12942
- fromChain: String(chainConfig.id),
12943
- fromToken: sourceToken,
12944
- fromAmount: usdfcAtomic.toString(),
12945
- toChain: String(314),
12946
- toToken: '0x80b98d3aa09ffff255c3ba4a241111ff1262f045',
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
- route: filRoute
12975
- });
12976
- logger.info(`FIL leg tx: ${chainConfig.explorer}/tx/${txHash}`), await waitForTransaction(provider, txHash), logger.info('FIL leg source tx confirmed; polling relayer…');
12977
- let status = await pollSquidStatus({
12978
- transactionId: txHash,
12979
- requestId: filRoute.params?.requestId,
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(` FIL poll #${n}: status=${s ?? '<none>'}`);
13206
+ verbose && logger.info(` bridge poll #${n}: status=${s ?? '<none>'}`);
12984
13207
  }
12985
- });
12986
- logger.success('FIL leg bridged'), result.filTxHash = txHash, result.filStatus = status;
12987
- }
12988
- if (usdfcRoute && usdfcParams) {
12989
- logger.info(`Executing USDfc leg on ${chainConfig.name}`);
12990
- let txHash = await executeRoute({
12991
- provider,
12992
- privateKey,
12993
- chainId: chainConfig.id,
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
- route: usdfcRoute
12996
- });
12997
- logger.info(`USDfc leg tx: ${chainConfig.explorer}/tx/${txHash}`), await waitForTransaction(provider, txHash), logger.info('USDfc leg source tx confirmed; polling relayer…');
12998
- let status = await pollSquidStatus({
12999
- transactionId: txHash,
13000
- requestId: usdfcRoute.params?.requestId,
13001
- fromChainId: String(chainConfig.id),
13002
- toChainId: String(314),
13003
- onAttempt: (n, s)=>{
13004
- verbose && logger.info(` USDfc poll #${n}: status=${s ?? '<none>'}`);
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
- return logger.success('Filecoin bridge complete'), result;
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: https://filfox.info/en/tx/${depositHash}`), await waitForTransaction(constants_filProvider[filecoinMainnet.id], depositHash), logger.success('Deposit confirmed'), {
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 input split to FIL (rest to USDfc). Filecoin only. Default 0.1.',
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
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnipin",
3
- "version": "3.0.0",
3
+ "version": "3.0.1",
4
4
  "author": "v1rtl <hi@v1rtl.site>",
5
5
  "repository": {
6
6
  "type": "git",