@stablechain/sdk 0.1.0 → 0.1.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.cjs CHANGED
@@ -79,9 +79,7 @@ function formatValue(v) {
79
79
  }
80
80
  }
81
81
 
82
- // src/services/layerzero.ts
83
-
84
-
82
+ // src/services/lifi.ts
85
83
 
86
84
 
87
85
 
@@ -103,6 +101,38 @@ function makeChain(id, rpc) {
103
101
  });
104
102
  }
105
103
 
104
+ // src/helpers/retry.ts
105
+ var HttpError = class extends Error {
106
+ constructor(message, status, retryable) {
107
+ super(message);
108
+ this.status = status;
109
+ this.retryable = retryable;
110
+ this.name = "HttpError";
111
+ }
112
+ };
113
+ function isRetryableError(err) {
114
+ if (err instanceof HttpError) return err.retryable;
115
+ return err instanceof TypeError;
116
+ }
117
+ async function retryWithBackoff(fn, isRetryable = isRetryableError, opts = {}) {
118
+ const maxAttempts = _nullishCoalesce(opts.maxAttempts, () => ( 3));
119
+ const base = _nullishCoalesce(opts.baseDelayMs, () => ( 250));
120
+ const max = _nullishCoalesce(opts.maxDelayMs, () => ( 4e3));
121
+ let lastErr;
122
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
123
+ try {
124
+ return await fn();
125
+ } catch (err) {
126
+ lastErr = err;
127
+ if (attempt === maxAttempts - 1 || !isRetryable(err)) throw err;
128
+ const delay = Math.min(max, base * 2 ** attempt);
129
+ const jittered = delay * (0.75 + Math.random() * 0.5);
130
+ await new Promise((r) => setTimeout(r, jittered));
131
+ }
132
+ }
133
+ throw lastErr;
134
+ }
135
+
106
136
  // src/types.ts
107
137
  var Chain = /* @__PURE__ */ ((Chain2) => {
108
138
  Chain2["Sepolia"] = "sepolia";
@@ -196,305 +226,6 @@ var CHAIN_CONFIGS = {
196
226
  }
197
227
  };
198
228
 
199
- // src/services/layerzero.ts
200
- var C = CHAIN_CONFIGS;
201
- var BRIDGE_CHAIN_CONFIGS = {
202
- // ─── Testnet ───────────────────────────────────────────────────────────────
203
- ["sepolia" /* Sepolia */]: { ...C["sepolia" /* Sepolia */], lzEid: 40161, oftAdapter: "0xc099cD946d5efCC35A99D64E808c1430cEf08126" },
204
- ["stable-testnet" /* StableTestnet */]: { ...C["stable-testnet" /* StableTestnet */], lzEid: 40374, oftAdapter: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736" },
205
- // ─── Mainnet ──────────────────────────────────────────────────────────────
206
- ["stable" /* Stable */]: { ...C["stable" /* Stable */], lzEid: 30396, oftAdapter: "0xedaba024be4d87974d5aB11C6Dd586963CcCB027" },
207
- ["ethereum" /* Ethereum */]: { ...C["ethereum" /* Ethereum */], lzEid: 30101, oftAdapter: "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee" },
208
- ["arbitrum" /* Arbitrum */]: { ...C["arbitrum" /* Arbitrum */], lzEid: 30110, oftAdapter: "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92" },
209
- ["ink" /* Ink */]: { ...C["ink" /* Ink */], lzEid: 30339, oftAdapter: "0x1cB6De532588fCA4a21B7209DE7C456AF8434A65" },
210
- ["bera" /* Bera */]: { ...C["bera" /* Bera */], lzEid: 30362, oftAdapter: "0x3Dc96399109df5ceb2C226664A086140bD0379cB" },
211
- ["megaeth" /* MegaETH */]: { ...C["megaeth" /* MegaETH */], lzEid: 30398, oftAdapter: "0x9151434b16b9763660705744891fa906f660ecc5" },
212
- ["hyperevm" /* HyperEVM */]: { ...C["hyperevm" /* HyperEVM */], lzEid: 30367, oftAdapter: "0x904861a24F30EC96ea7CFC3bE9EA4B476d237e98" }
213
- };
214
- var OFT_ADAPTER_ABI = [
215
- {
216
- name: "quoteSend",
217
- type: "function",
218
- inputs: [
219
- {
220
- name: "_sendParam",
221
- type: "tuple",
222
- components: [
223
- { name: "dstEid", type: "uint32" },
224
- { name: "to", type: "bytes32" },
225
- { name: "amountLD", type: "uint256" },
226
- { name: "minAmountLD", type: "uint256" },
227
- { name: "extraOptions", type: "bytes" },
228
- { name: "composeMsg", type: "bytes" },
229
- { name: "oftCmd", type: "bytes" }
230
- ]
231
- },
232
- { name: "_payInLzToken", type: "bool" }
233
- ],
234
- outputs: [
235
- {
236
- name: "msgFee",
237
- type: "tuple",
238
- components: [
239
- { name: "nativeFee", type: "uint256" },
240
- { name: "lzTokenFee", type: "uint256" }
241
- ]
242
- }
243
- ],
244
- stateMutability: "view"
245
- },
246
- {
247
- name: "send",
248
- type: "function",
249
- inputs: [
250
- {
251
- name: "_sendParam",
252
- type: "tuple",
253
- components: [
254
- { name: "dstEid", type: "uint32" },
255
- { name: "to", type: "bytes32" },
256
- { name: "amountLD", type: "uint256" },
257
- { name: "minAmountLD", type: "uint256" },
258
- { name: "extraOptions", type: "bytes" },
259
- { name: "composeMsg", type: "bytes" },
260
- { name: "oftCmd", type: "bytes" }
261
- ]
262
- },
263
- {
264
- name: "_fee",
265
- type: "tuple",
266
- components: [
267
- { name: "nativeFee", type: "uint256" },
268
- { name: "lzTokenFee", type: "uint256" }
269
- ]
270
- },
271
- { name: "_refundAddress", type: "address" }
272
- ],
273
- outputs: [],
274
- stateMutability: "payable"
275
- }
276
- ];
277
- function buildLzOptions(gasLimit = 0n) {
278
- return _viem.concat.call(void 0, [
279
- _viem.numberToHex.call(void 0, 3, { size: 2 }),
280
- // TYPE_3 header
281
- _viem.numberToHex.call(void 0, 1, { size: 1 }),
282
- // Executor worker ID
283
- _viem.numberToHex.call(void 0, 17, { size: 2 }),
284
- // option payload length = 17 bytes
285
- _viem.numberToHex.call(void 0, 1, { size: 1 }),
286
- // LzReceive option type
287
- _viem.numberToHex.call(void 0, gasLimit, { size: 16 })
288
- // gas limit as uint128
289
- ]);
290
- }
291
- var LayerZeroService = class {
292
- constructor(config) {
293
- this.config = config;
294
- }
295
- async quoteBridge({ fromChain, toChain, amount, recipient }) {
296
- const recipientAddr = _nullishCoalesce(recipient, () => ( "0x0000000000000000000000000000000000000000"));
297
- this.validateBridgeParams({ fromChain, toChain, amount, recipient: recipientAddr }, "quoteBridge");
298
- const { src, dst } = this.resolveChains(fromChain, toChain);
299
- const oftAdapter = src.oftAdapter;
300
- const amountLD = _viem.parseUnits.call(void 0, String(amount), src.decimals);
301
- try {
302
- const { nativeFee, lzTokenFee } = await _viem.createPublicClient.call(void 0, {
303
- chain: makeChain(src.id, src.rpc),
304
- transport: _viem.http.call(void 0, src.rpc)
305
- }).readContract({
306
- address: oftAdapter,
307
- abi: OFT_ADAPTER_ABI,
308
- functionName: "quoteSend",
309
- args: [this.buildSendParams(dst, amountLD, recipientAddr), false]
310
- });
311
- return { nativeFee, lzTokenFee, toAmount: amount };
312
- } catch (err) {
313
- throw new StableQuoteError({
314
- provider: "layerzero",
315
- shortMessage: "quoteBridge: quoteSend call failed",
316
- cause: err
317
- });
318
- }
319
- }
320
- async bridge({ fromChain, toChain, fromToken, toToken, amount, recipient, quote }) {
321
- const from = _nullishCoalesce(_optionalChain([this, 'access', _2 => _2.config, 'access', _3 => _3.walletClient, 'optionalAccess', _4 => _4.account, 'optionalAccess', _5 => _5.address]), () => ( _optionalChain([this, 'access', _6 => _6.config, 'access', _7 => _7.account, 'optionalAccess', _8 => _8.address])));
322
- if (!from) {
323
- throw new StableValidationError(
324
- "signer",
325
- void 0,
326
- "bridge: requires a signer \u2014 set walletClient or account in StableConfig"
327
- );
328
- }
329
- const recipientAddr = _nullishCoalesce(recipient, () => ( from));
330
- this.validateBridgeParams({ fromChain, toChain, amount, recipient: recipientAddr }, "bridge");
331
- const { src, dst } = this.resolveChains(fromChain, toChain);
332
- const oftAdapter = src.oftAdapter;
333
- const srcChain = makeChain(src.id, src.rpc);
334
- const wc = _nullishCoalesce(this.config.walletClient, () => ( _viem.createWalletClient.call(void 0, {
335
- account: this.config.account,
336
- chain: srcChain,
337
- transport: _nullishCoalesce(this.config.transport, () => ( _viem.http.call(void 0, src.rpc)))
338
- })));
339
- const pc = _viem.createPublicClient.call(void 0, { chain: srcChain, transport: _viem.http.call(void 0, src.rpc) });
340
- try {
341
- await wc.switchChain({ id: src.id });
342
- } catch (err) {
343
- throw new StableTransactionError({
344
- phase: "switch_chain",
345
- shortMessage: `bridge: wallet rejected or failed to switch to chain ${src.id}`,
346
- chainId: src.id,
347
- cause: err
348
- });
349
- }
350
- const amountLD = _viem.parseUnits.call(void 0, String(amount), src.decimals);
351
- const sendParams = this.buildSendParams(dst, amountLD, recipientAddr);
352
- const lzFee = _optionalChain([quote, 'optionalAccess', _9 => _9.nativeFee]) !== void 0 && _optionalChain([quote, 'optionalAccess', _10 => _10.lzTokenFee]) !== void 0 ? { nativeFee: quote.nativeFee, lzTokenFee: quote.lzTokenFee } : await this.quoteBridge({ fromChain, toChain, fromToken, toToken, amount, recipient: recipientAddr });
353
- const { nativeFee = 0n, lzTokenFee = 0n } = lzFee;
354
- const allowance = await pc.readContract({
355
- address: src.usdt,
356
- abi: _viem.erc20Abi,
357
- functionName: "allowance",
358
- args: [from, oftAdapter]
359
- });
360
- if (allowance < amountLD) {
361
- let approveHash;
362
- try {
363
- approveHash = await wc.writeContract({
364
- address: src.usdt,
365
- abi: _viem.erc20Abi,
366
- functionName: "approve",
367
- args: [oftAdapter, amountLD],
368
- account: wc.account,
369
- chain: srcChain
370
- });
371
- } catch (err) {
372
- throw new StableTransactionError({
373
- phase: "approve",
374
- shortMessage: "bridge: USDT0 approve failed",
375
- chainId: src.id,
376
- cause: err
377
- });
378
- }
379
- const approveReceipt = await pc.waitForTransactionReceipt({ hash: approveHash });
380
- if (approveReceipt.status === "reverted") {
381
- throw new StableTransactionError({
382
- phase: "approve",
383
- shortMessage: "bridge: USDT0 approve reverted on-chain",
384
- txHash: approveReceipt.transactionHash,
385
- chainId: src.id
386
- });
387
- }
388
- }
389
- try {
390
- const hash = await wc.writeContract({
391
- address: oftAdapter,
392
- abi: OFT_ADAPTER_ABI,
393
- functionName: "send",
394
- args: [sendParams, { nativeFee, lzTokenFee }, from],
395
- value: nativeFee,
396
- account: wc.account,
397
- chain: srcChain
398
- });
399
- return { txHash: hash, toAmount: amount };
400
- } catch (err) {
401
- throw new StableTransactionError({
402
- phase: "send",
403
- shortMessage: "bridge: OFT send failed",
404
- chainId: src.id,
405
- cause: err
406
- });
407
- }
408
- }
409
- validateBridgeParams(params, method) {
410
- if (!_viem.isAddress.call(void 0, params.recipient)) {
411
- throw new StableValidationError(
412
- "recipient",
413
- params.recipient,
414
- `${method}: invalid recipient address "${params.recipient}"`
415
- );
416
- }
417
- if (!Number.isFinite(params.amount) || params.amount <= 0) {
418
- throw new StableValidationError(
419
- "amount",
420
- params.amount,
421
- `${method}: amount must be a finite positive number`
422
- );
423
- }
424
- if (params.fromChain === params.toChain) {
425
- throw new StableValidationError(
426
- "toChain",
427
- params.toChain,
428
- `${method}: fromChain and toChain must differ`
429
- );
430
- }
431
- }
432
- resolveChains(fromChain, toChain) {
433
- const src = BRIDGE_CHAIN_CONFIGS[fromChain];
434
- const dst = BRIDGE_CHAIN_CONFIGS[toChain];
435
- if (!src) throw new StableValidationError("fromChain", fromChain, `Unsupported source chain: "${fromChain}"`);
436
- if (!dst) throw new StableValidationError("toChain", toChain, `Unsupported destination chain: "${toChain}"`);
437
- if (!src.oftAdapter) {
438
- throw new StableValidationError("fromChain", fromChain, `No OFT adapter configured for "${fromChain}"`);
439
- }
440
- return { src, dst };
441
- }
442
- buildSendParams(dst, amountLD, recipient) {
443
- return {
444
- dstEid: dst.lzEid,
445
- to: _viem.padHex.call(void 0, recipient, { dir: "left", size: 32 }),
446
- amountLD,
447
- minAmountLD: amountLD,
448
- extraOptions: buildLzOptions(),
449
- composeMsg: "0x",
450
- oftCmd: "0x"
451
- };
452
- }
453
- };
454
-
455
- // src/services/lifi.ts
456
-
457
-
458
-
459
-
460
-
461
-
462
-
463
-
464
-
465
-
466
- // src/helpers/retry.ts
467
- var HttpError = class extends Error {
468
- constructor(message, status, retryable) {
469
- super(message);
470
- this.status = status;
471
- this.retryable = retryable;
472
- this.name = "HttpError";
473
- }
474
- };
475
- function isRetryableError(err) {
476
- if (err instanceof HttpError) return err.retryable;
477
- return err instanceof TypeError;
478
- }
479
- async function retryWithBackoff(fn, isRetryable = isRetryableError, opts = {}) {
480
- const maxAttempts = _nullishCoalesce(opts.maxAttempts, () => ( 3));
481
- const base = _nullishCoalesce(opts.baseDelayMs, () => ( 250));
482
- const max = _nullishCoalesce(opts.maxDelayMs, () => ( 4e3));
483
- let lastErr;
484
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
485
- try {
486
- return await fn();
487
- } catch (err) {
488
- lastErr = err;
489
- if (attempt === maxAttempts - 1 || !isRetryable(err)) throw err;
490
- const delay = Math.min(max, base * 2 ** attempt);
491
- const jittered = delay * (0.75 + Math.random() * 0.5);
492
- await new Promise((r) => setTimeout(r, jittered));
493
- }
494
- }
495
- throw lastErr;
496
- }
497
-
498
229
  // src/services/lifi.ts
499
230
  var LiFiService = class {
500
231
  constructor(config) {
@@ -526,7 +257,7 @@ var LiFiService = class {
526
257
  async quoteBridge(params) {
527
258
  this._validateBridgeParams(params);
528
259
  const { fromChain, toChain, fromToken, toToken, amount, fromDecimals = 6, recipient } = params;
529
- const from = _nullishCoalesce(_nullishCoalesce(_optionalChain([this, 'access', _11 => _11.config, 'access', _12 => _12.walletClient, 'optionalAccess', _13 => _13.account, 'optionalAccess', _14 => _14.address]), () => ( _optionalChain([this, 'access', _15 => _15.config, 'access', _16 => _16.account, 'optionalAccess', _17 => _17.address]))), () => ( "0x0000000000000000000000000000000000000000"));
260
+ const from = _nullishCoalesce(_nullishCoalesce(_optionalChain([this, 'access', _2 => _2.config, 'access', _3 => _3.walletClient, 'optionalAccess', _4 => _4.account, 'optionalAccess', _5 => _5.address]), () => ( _optionalChain([this, 'access', _6 => _6.config, 'access', _7 => _7.account, 'optionalAccess', _8 => _8.address]))), () => ( "0x0000000000000000000000000000000000000000"));
530
261
  const src = CHAIN_CONFIGS[fromChain];
531
262
  const dst = CHAIN_CONFIGS[toChain];
532
263
  if (!src) throw new StableValidationError("fromChain", fromChain, `LI.FI bridge: unsupported source chain "${fromChain}"`);
@@ -603,7 +334,7 @@ var LiFiService = class {
603
334
  }
604
335
  }
605
336
  _requireFrom() {
606
- const from = _nullishCoalesce(_optionalChain([this, 'access', _18 => _18.config, 'access', _19 => _19.walletClient, 'optionalAccess', _20 => _20.account, 'optionalAccess', _21 => _21.address]), () => ( _optionalChain([this, 'access', _22 => _22.config, 'access', _23 => _23.account, 'optionalAccess', _24 => _24.address])));
337
+ const from = _nullishCoalesce(_optionalChain([this, 'access', _9 => _9.config, 'access', _10 => _10.walletClient, 'optionalAccess', _11 => _11.account, 'optionalAccess', _12 => _12.address]), () => ( _optionalChain([this, 'access', _13 => _13.config, 'access', _14 => _14.account, 'optionalAccess', _15 => _15.address])));
607
338
  if (!from) {
608
339
  throw new StableValidationError(
609
340
  "signer",
@@ -772,11 +503,6 @@ function isLiFiQuoteShape(v) {
772
503
  }
773
504
 
774
505
  // src/stable.ts
775
- function isUsdt0Route(fromChain, toChain, fromToken, toToken) {
776
- const src = BRIDGE_CHAIN_CONFIGS[fromChain];
777
- const dst = BRIDGE_CHAIN_CONFIGS[toChain];
778
- return !!src && !!dst && src.lzOutbound !== false && src.usdt.toLowerCase() === fromToken.toLowerCase() && dst.usdt.toLowerCase() === toToken.toLowerCase();
779
- }
780
506
  function validateTransferParams({ to, amount, token, tokenDecimals }) {
781
507
  if (!_viem.isAddress.call(void 0, to)) {
782
508
  throw new StableValidationError("to", to, `transfer: invalid recipient address "${to}"`);
@@ -832,12 +558,11 @@ function createStable({
832
558
  const chain = network === "mainnet" /* Mainnet */ ? _chains.stable : _chains.stableTestnet;
833
559
  const rpc = (_nullishCoalesce(rpcOverride, () => ( chain.rpcUrls.default.http[0]))).replace(/\/$/, "");
834
560
  const signerConfig = { account, transport, walletClient };
835
- const lz = new LayerZeroService(signerConfig);
836
561
  const lifi = new LiFiService({ ...signerConfig, rpc, chainId: chain.id });
837
562
  async function transfer(params) {
838
563
  validateTransferParams(params);
839
564
  const { from, to, amount, token, tokenDecimals } = params;
840
- const acc = _nullishCoalesce(_nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _25 => _25.account]), () => ( account)), () => ( from));
565
+ const acc = _nullishCoalesce(_nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _16 => _16.account]), () => ( account)), () => ( from));
841
566
  const wc = _nullishCoalesce(walletClient, () => ( _viem.createWalletClient.call(void 0, {
842
567
  account: acc,
843
568
  chain,
@@ -867,10 +592,10 @@ function createStable({
867
592
  return { txHash: receipt.transactionHash };
868
593
  }
869
594
  function quoteBridge(params) {
870
- return isUsdt0Route(params.fromChain, params.toChain, params.fromToken, params.toToken) ? lz.quoteBridge(params) : lifi.quoteBridge(params);
595
+ return lifi.quoteBridge(params);
871
596
  }
872
597
  function bridge(params) {
873
- return isUsdt0Route(params.fromChain, params.toChain, params.fromToken, params.toToken) ? lz.bridge(params) : lifi.bridge(params);
598
+ return lifi.bridge(params);
874
599
  }
875
600
  return {
876
601
  transfer,
package/dist/index.d.cts CHANGED
@@ -82,9 +82,6 @@ declare enum Network {
82
82
  interface BridgeQuote {
83
83
  /** Estimated output amount on the destination chain */
84
84
  toAmount?: number;
85
- /** LayerZero native fee — only present for USDT0→USDT0 routes */
86
- nativeFee?: bigint;
87
- lzTokenFee?: bigint;
88
85
  }
89
86
  interface BridgeParams {
90
87
  fromChain: Chain;
@@ -98,7 +95,7 @@ interface BridgeParams {
98
95
  fromDecimals?: number;
99
96
  /** Recipient address — defaults to the signer */
100
97
  recipient?: string;
101
- /** Pre-fetched quote from quoteBridge() — skips the LayerZero quoteSend for USDT0 routes */
98
+ /** Pre-fetched quote from quoteBridge() — skips the quote fetch when passed to bridge() */
102
99
  quote?: BridgeQuote;
103
100
  }
104
101
 
@@ -130,12 +127,12 @@ declare class StableValidationError extends StableError {
130
127
  });
131
128
  }
132
129
  declare class StableQuoteError extends StableError {
133
- provider: "layerzero" | "lifi";
130
+ provider: string;
134
131
  httpStatus?: number;
135
132
  providerCode?: string;
136
133
  body?: unknown;
137
134
  constructor(args: {
138
- provider: "layerzero" | "lifi";
135
+ provider: string;
139
136
  shortMessage: string;
140
137
  httpStatus?: number;
141
138
  providerCode?: string;
package/dist/index.d.ts CHANGED
@@ -82,9 +82,6 @@ declare enum Network {
82
82
  interface BridgeQuote {
83
83
  /** Estimated output amount on the destination chain */
84
84
  toAmount?: number;
85
- /** LayerZero native fee — only present for USDT0→USDT0 routes */
86
- nativeFee?: bigint;
87
- lzTokenFee?: bigint;
88
85
  }
89
86
  interface BridgeParams {
90
87
  fromChain: Chain;
@@ -98,7 +95,7 @@ interface BridgeParams {
98
95
  fromDecimals?: number;
99
96
  /** Recipient address — defaults to the signer */
100
97
  recipient?: string;
101
- /** Pre-fetched quote from quoteBridge() — skips the LayerZero quoteSend for USDT0 routes */
98
+ /** Pre-fetched quote from quoteBridge() — skips the quote fetch when passed to bridge() */
102
99
  quote?: BridgeQuote;
103
100
  }
104
101
 
@@ -130,12 +127,12 @@ declare class StableValidationError extends StableError {
130
127
  });
131
128
  }
132
129
  declare class StableQuoteError extends StableError {
133
- provider: "layerzero" | "lifi";
130
+ provider: string;
134
131
  httpStatus?: number;
135
132
  providerCode?: string;
136
133
  body?: unknown;
137
134
  constructor(args: {
138
- provider: "layerzero" | "lifi";
135
+ provider: string;
139
136
  shortMessage: string;
140
137
  httpStatus?: number;
141
138
  providerCode?: string;
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  // src/stable.ts
2
2
  import {
3
- createPublicClient as createPublicClient3,
4
- createWalletClient as createWalletClient3,
5
- erc20Abi as erc20Abi3,
6
- http as http3,
7
- isAddress as isAddress3,
8
- parseUnits as parseUnits3
3
+ createPublicClient as createPublicClient2,
4
+ createWalletClient as createWalletClient2,
5
+ erc20Abi as erc20Abi2,
6
+ http as http2,
7
+ isAddress as isAddress2,
8
+ parseUnits as parseUnits2
9
9
  } from "viem";
10
10
  import { stable as stableMainnet, stableTestnet } from "viem/chains";
11
11
 
@@ -79,16 +79,14 @@ function formatValue(v) {
79
79
  }
80
80
  }
81
81
 
82
- // src/services/layerzero.ts
82
+ // src/services/lifi.ts
83
83
  import {
84
- concat,
85
84
  createPublicClient,
86
85
  createWalletClient,
87
86
  erc20Abi,
87
+ formatUnits,
88
88
  http,
89
89
  isAddress,
90
- numberToHex,
91
- padHex,
92
90
  parseUnits
93
91
  } from "viem";
94
92
 
@@ -103,6 +101,38 @@ function makeChain(id, rpc) {
103
101
  });
104
102
  }
105
103
 
104
+ // src/helpers/retry.ts
105
+ var HttpError = class extends Error {
106
+ constructor(message, status, retryable) {
107
+ super(message);
108
+ this.status = status;
109
+ this.retryable = retryable;
110
+ this.name = "HttpError";
111
+ }
112
+ };
113
+ function isRetryableError(err) {
114
+ if (err instanceof HttpError) return err.retryable;
115
+ return err instanceof TypeError;
116
+ }
117
+ async function retryWithBackoff(fn, isRetryable = isRetryableError, opts = {}) {
118
+ const maxAttempts = opts.maxAttempts ?? 3;
119
+ const base = opts.baseDelayMs ?? 250;
120
+ const max = opts.maxDelayMs ?? 4e3;
121
+ let lastErr;
122
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
123
+ try {
124
+ return await fn();
125
+ } catch (err) {
126
+ lastErr = err;
127
+ if (attempt === maxAttempts - 1 || !isRetryable(err)) throw err;
128
+ const delay = Math.min(max, base * 2 ** attempt);
129
+ const jittered = delay * (0.75 + Math.random() * 0.5);
130
+ await new Promise((r) => setTimeout(r, jittered));
131
+ }
132
+ }
133
+ throw lastErr;
134
+ }
135
+
106
136
  // src/types.ts
107
137
  var Chain = /* @__PURE__ */ ((Chain2) => {
108
138
  Chain2["Sepolia"] = "sepolia";
@@ -196,305 +226,6 @@ var CHAIN_CONFIGS = {
196
226
  }
197
227
  };
198
228
 
199
- // src/services/layerzero.ts
200
- var C = CHAIN_CONFIGS;
201
- var BRIDGE_CHAIN_CONFIGS = {
202
- // ─── Testnet ───────────────────────────────────────────────────────────────
203
- ["sepolia" /* Sepolia */]: { ...C["sepolia" /* Sepolia */], lzEid: 40161, oftAdapter: "0xc099cD946d5efCC35A99D64E808c1430cEf08126" },
204
- ["stable-testnet" /* StableTestnet */]: { ...C["stable-testnet" /* StableTestnet */], lzEid: 40374, oftAdapter: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736" },
205
- // ─── Mainnet ──────────────────────────────────────────────────────────────
206
- ["stable" /* Stable */]: { ...C["stable" /* Stable */], lzEid: 30396, oftAdapter: "0xedaba024be4d87974d5aB11C6Dd586963CcCB027" },
207
- ["ethereum" /* Ethereum */]: { ...C["ethereum" /* Ethereum */], lzEid: 30101, oftAdapter: "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee" },
208
- ["arbitrum" /* Arbitrum */]: { ...C["arbitrum" /* Arbitrum */], lzEid: 30110, oftAdapter: "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92" },
209
- ["ink" /* Ink */]: { ...C["ink" /* Ink */], lzEid: 30339, oftAdapter: "0x1cB6De532588fCA4a21B7209DE7C456AF8434A65" },
210
- ["bera" /* Bera */]: { ...C["bera" /* Bera */], lzEid: 30362, oftAdapter: "0x3Dc96399109df5ceb2C226664A086140bD0379cB" },
211
- ["megaeth" /* MegaETH */]: { ...C["megaeth" /* MegaETH */], lzEid: 30398, oftAdapter: "0x9151434b16b9763660705744891fa906f660ecc5" },
212
- ["hyperevm" /* HyperEVM */]: { ...C["hyperevm" /* HyperEVM */], lzEid: 30367, oftAdapter: "0x904861a24F30EC96ea7CFC3bE9EA4B476d237e98" }
213
- };
214
- var OFT_ADAPTER_ABI = [
215
- {
216
- name: "quoteSend",
217
- type: "function",
218
- inputs: [
219
- {
220
- name: "_sendParam",
221
- type: "tuple",
222
- components: [
223
- { name: "dstEid", type: "uint32" },
224
- { name: "to", type: "bytes32" },
225
- { name: "amountLD", type: "uint256" },
226
- { name: "minAmountLD", type: "uint256" },
227
- { name: "extraOptions", type: "bytes" },
228
- { name: "composeMsg", type: "bytes" },
229
- { name: "oftCmd", type: "bytes" }
230
- ]
231
- },
232
- { name: "_payInLzToken", type: "bool" }
233
- ],
234
- outputs: [
235
- {
236
- name: "msgFee",
237
- type: "tuple",
238
- components: [
239
- { name: "nativeFee", type: "uint256" },
240
- { name: "lzTokenFee", type: "uint256" }
241
- ]
242
- }
243
- ],
244
- stateMutability: "view"
245
- },
246
- {
247
- name: "send",
248
- type: "function",
249
- inputs: [
250
- {
251
- name: "_sendParam",
252
- type: "tuple",
253
- components: [
254
- { name: "dstEid", type: "uint32" },
255
- { name: "to", type: "bytes32" },
256
- { name: "amountLD", type: "uint256" },
257
- { name: "minAmountLD", type: "uint256" },
258
- { name: "extraOptions", type: "bytes" },
259
- { name: "composeMsg", type: "bytes" },
260
- { name: "oftCmd", type: "bytes" }
261
- ]
262
- },
263
- {
264
- name: "_fee",
265
- type: "tuple",
266
- components: [
267
- { name: "nativeFee", type: "uint256" },
268
- { name: "lzTokenFee", type: "uint256" }
269
- ]
270
- },
271
- { name: "_refundAddress", type: "address" }
272
- ],
273
- outputs: [],
274
- stateMutability: "payable"
275
- }
276
- ];
277
- function buildLzOptions(gasLimit = 0n) {
278
- return concat([
279
- numberToHex(3, { size: 2 }),
280
- // TYPE_3 header
281
- numberToHex(1, { size: 1 }),
282
- // Executor worker ID
283
- numberToHex(17, { size: 2 }),
284
- // option payload length = 17 bytes
285
- numberToHex(1, { size: 1 }),
286
- // LzReceive option type
287
- numberToHex(gasLimit, { size: 16 })
288
- // gas limit as uint128
289
- ]);
290
- }
291
- var LayerZeroService = class {
292
- constructor(config) {
293
- this.config = config;
294
- }
295
- async quoteBridge({ fromChain, toChain, amount, recipient }) {
296
- const recipientAddr = recipient ?? "0x0000000000000000000000000000000000000000";
297
- this.validateBridgeParams({ fromChain, toChain, amount, recipient: recipientAddr }, "quoteBridge");
298
- const { src, dst } = this.resolveChains(fromChain, toChain);
299
- const oftAdapter = src.oftAdapter;
300
- const amountLD = parseUnits(String(amount), src.decimals);
301
- try {
302
- const { nativeFee, lzTokenFee } = await createPublicClient({
303
- chain: makeChain(src.id, src.rpc),
304
- transport: http(src.rpc)
305
- }).readContract({
306
- address: oftAdapter,
307
- abi: OFT_ADAPTER_ABI,
308
- functionName: "quoteSend",
309
- args: [this.buildSendParams(dst, amountLD, recipientAddr), false]
310
- });
311
- return { nativeFee, lzTokenFee, toAmount: amount };
312
- } catch (err) {
313
- throw new StableQuoteError({
314
- provider: "layerzero",
315
- shortMessage: "quoteBridge: quoteSend call failed",
316
- cause: err
317
- });
318
- }
319
- }
320
- async bridge({ fromChain, toChain, fromToken, toToken, amount, recipient, quote }) {
321
- const from = this.config.walletClient?.account?.address ?? this.config.account?.address;
322
- if (!from) {
323
- throw new StableValidationError(
324
- "signer",
325
- void 0,
326
- "bridge: requires a signer \u2014 set walletClient or account in StableConfig"
327
- );
328
- }
329
- const recipientAddr = recipient ?? from;
330
- this.validateBridgeParams({ fromChain, toChain, amount, recipient: recipientAddr }, "bridge");
331
- const { src, dst } = this.resolveChains(fromChain, toChain);
332
- const oftAdapter = src.oftAdapter;
333
- const srcChain = makeChain(src.id, src.rpc);
334
- const wc = this.config.walletClient ?? createWalletClient({
335
- account: this.config.account,
336
- chain: srcChain,
337
- transport: this.config.transport ?? http(src.rpc)
338
- });
339
- const pc = createPublicClient({ chain: srcChain, transport: http(src.rpc) });
340
- try {
341
- await wc.switchChain({ id: src.id });
342
- } catch (err) {
343
- throw new StableTransactionError({
344
- phase: "switch_chain",
345
- shortMessage: `bridge: wallet rejected or failed to switch to chain ${src.id}`,
346
- chainId: src.id,
347
- cause: err
348
- });
349
- }
350
- const amountLD = parseUnits(String(amount), src.decimals);
351
- const sendParams = this.buildSendParams(dst, amountLD, recipientAddr);
352
- const lzFee = quote?.nativeFee !== void 0 && quote?.lzTokenFee !== void 0 ? { nativeFee: quote.nativeFee, lzTokenFee: quote.lzTokenFee } : await this.quoteBridge({ fromChain, toChain, fromToken, toToken, amount, recipient: recipientAddr });
353
- const { nativeFee = 0n, lzTokenFee = 0n } = lzFee;
354
- const allowance = await pc.readContract({
355
- address: src.usdt,
356
- abi: erc20Abi,
357
- functionName: "allowance",
358
- args: [from, oftAdapter]
359
- });
360
- if (allowance < amountLD) {
361
- let approveHash;
362
- try {
363
- approveHash = await wc.writeContract({
364
- address: src.usdt,
365
- abi: erc20Abi,
366
- functionName: "approve",
367
- args: [oftAdapter, amountLD],
368
- account: wc.account,
369
- chain: srcChain
370
- });
371
- } catch (err) {
372
- throw new StableTransactionError({
373
- phase: "approve",
374
- shortMessage: "bridge: USDT0 approve failed",
375
- chainId: src.id,
376
- cause: err
377
- });
378
- }
379
- const approveReceipt = await pc.waitForTransactionReceipt({ hash: approveHash });
380
- if (approveReceipt.status === "reverted") {
381
- throw new StableTransactionError({
382
- phase: "approve",
383
- shortMessage: "bridge: USDT0 approve reverted on-chain",
384
- txHash: approveReceipt.transactionHash,
385
- chainId: src.id
386
- });
387
- }
388
- }
389
- try {
390
- const hash = await wc.writeContract({
391
- address: oftAdapter,
392
- abi: OFT_ADAPTER_ABI,
393
- functionName: "send",
394
- args: [sendParams, { nativeFee, lzTokenFee }, from],
395
- value: nativeFee,
396
- account: wc.account,
397
- chain: srcChain
398
- });
399
- return { txHash: hash, toAmount: amount };
400
- } catch (err) {
401
- throw new StableTransactionError({
402
- phase: "send",
403
- shortMessage: "bridge: OFT send failed",
404
- chainId: src.id,
405
- cause: err
406
- });
407
- }
408
- }
409
- validateBridgeParams(params, method) {
410
- if (!isAddress(params.recipient)) {
411
- throw new StableValidationError(
412
- "recipient",
413
- params.recipient,
414
- `${method}: invalid recipient address "${params.recipient}"`
415
- );
416
- }
417
- if (!Number.isFinite(params.amount) || params.amount <= 0) {
418
- throw new StableValidationError(
419
- "amount",
420
- params.amount,
421
- `${method}: amount must be a finite positive number`
422
- );
423
- }
424
- if (params.fromChain === params.toChain) {
425
- throw new StableValidationError(
426
- "toChain",
427
- params.toChain,
428
- `${method}: fromChain and toChain must differ`
429
- );
430
- }
431
- }
432
- resolveChains(fromChain, toChain) {
433
- const src = BRIDGE_CHAIN_CONFIGS[fromChain];
434
- const dst = BRIDGE_CHAIN_CONFIGS[toChain];
435
- if (!src) throw new StableValidationError("fromChain", fromChain, `Unsupported source chain: "${fromChain}"`);
436
- if (!dst) throw new StableValidationError("toChain", toChain, `Unsupported destination chain: "${toChain}"`);
437
- if (!src.oftAdapter) {
438
- throw new StableValidationError("fromChain", fromChain, `No OFT adapter configured for "${fromChain}"`);
439
- }
440
- return { src, dst };
441
- }
442
- buildSendParams(dst, amountLD, recipient) {
443
- return {
444
- dstEid: dst.lzEid,
445
- to: padHex(recipient, { dir: "left", size: 32 }),
446
- amountLD,
447
- minAmountLD: amountLD,
448
- extraOptions: buildLzOptions(),
449
- composeMsg: "0x",
450
- oftCmd: "0x"
451
- };
452
- }
453
- };
454
-
455
- // src/services/lifi.ts
456
- import {
457
- createPublicClient as createPublicClient2,
458
- createWalletClient as createWalletClient2,
459
- erc20Abi as erc20Abi2,
460
- formatUnits,
461
- http as http2,
462
- isAddress as isAddress2,
463
- parseUnits as parseUnits2
464
- } from "viem";
465
-
466
- // src/helpers/retry.ts
467
- var HttpError = class extends Error {
468
- constructor(message, status, retryable) {
469
- super(message);
470
- this.status = status;
471
- this.retryable = retryable;
472
- this.name = "HttpError";
473
- }
474
- };
475
- function isRetryableError(err) {
476
- if (err instanceof HttpError) return err.retryable;
477
- return err instanceof TypeError;
478
- }
479
- async function retryWithBackoff(fn, isRetryable = isRetryableError, opts = {}) {
480
- const maxAttempts = opts.maxAttempts ?? 3;
481
- const base = opts.baseDelayMs ?? 250;
482
- const max = opts.maxDelayMs ?? 4e3;
483
- let lastErr;
484
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
485
- try {
486
- return await fn();
487
- } catch (err) {
488
- lastErr = err;
489
- if (attempt === maxAttempts - 1 || !isRetryable(err)) throw err;
490
- const delay = Math.min(max, base * 2 ** attempt);
491
- const jittered = delay * (0.75 + Math.random() * 0.5);
492
- await new Promise((r) => setTimeout(r, jittered));
493
- }
494
- }
495
- throw lastErr;
496
- }
497
-
498
229
  // src/services/lifi.ts
499
230
  var LiFiService = class {
500
231
  constructor(config) {
@@ -505,7 +236,7 @@ var LiFiService = class {
505
236
  const { fromToken, toToken, amount, fromDecimals = 6, toAddress } = params;
506
237
  const from = this._requireFrom();
507
238
  const chain = this.config.chainId.toString();
508
- const fromAmountRaw = parseUnits2(String(amount), fromDecimals).toString();
239
+ const fromAmountRaw = parseUnits(String(amount), fromDecimals).toString();
509
240
  const qs = new URLSearchParams({
510
241
  fromChain: chain,
511
242
  toChain: chain,
@@ -536,7 +267,7 @@ var LiFiService = class {
536
267
  toChain: dst.id.toString(),
537
268
  fromToken,
538
269
  toToken,
539
- fromAmount: parseUnits2(String(amount), fromDecimals).toString(),
270
+ fromAmount: parseUnits(String(amount), fromDecimals).toString(),
540
271
  fromAddress: from,
541
272
  ...recipient && { toAddress: recipient }
542
273
  });
@@ -555,7 +286,7 @@ var LiFiService = class {
555
286
  if (!dst) {
556
287
  throw new StableValidationError("toChain", toChain, `LI.FI bridge: unsupported destination chain "${toChain}"`);
557
288
  }
558
- const fromAmountRaw = parseUnits2(String(amount), fromDecimals).toString();
289
+ const fromAmountRaw = parseUnits(String(amount), fromDecimals).toString();
559
290
  const qs = new URLSearchParams({
560
291
  fromChain: src.id.toString(),
561
292
  toChain: dst.id.toString(),
@@ -569,10 +300,10 @@ var LiFiService = class {
569
300
  return this._executeSwapQuote(quote, src.rpc, src.id);
570
301
  }
571
302
  _validateSwapParams({ fromToken, toToken, amount, toAddress }) {
572
- if (!isAddress2(fromToken)) {
303
+ if (!isAddress(fromToken)) {
573
304
  throw new StableValidationError("fromToken", fromToken, `swap: invalid fromToken address "${fromToken}"`);
574
305
  }
575
- if (!isAddress2(toToken)) {
306
+ if (!isAddress(toToken)) {
576
307
  throw new StableValidationError("toToken", toToken, `swap: invalid toToken address "${toToken}"`);
577
308
  }
578
309
  if (fromToken.toLowerCase() === toToken.toLowerCase()) {
@@ -581,21 +312,21 @@ var LiFiService = class {
581
312
  if (!Number.isFinite(amount) || amount <= 0) {
582
313
  throw new StableValidationError("amount", amount, "swap: amount must be a finite positive number");
583
314
  }
584
- if (toAddress !== void 0 && !isAddress2(toAddress)) {
315
+ if (toAddress !== void 0 && !isAddress(toAddress)) {
585
316
  throw new StableValidationError("toAddress", toAddress, `swap: invalid toAddress "${toAddress}"`);
586
317
  }
587
318
  }
588
319
  _validateBridgeParams({ fromChain, toChain, fromToken, toToken, amount, recipient }) {
589
- if (!isAddress2(fromToken)) {
320
+ if (!isAddress(fromToken)) {
590
321
  throw new StableValidationError("fromToken", fromToken, `LI.FI bridge: invalid fromToken address "${fromToken}"`);
591
322
  }
592
- if (!isAddress2(toToken)) {
323
+ if (!isAddress(toToken)) {
593
324
  throw new StableValidationError("toToken", toToken, `LI.FI bridge: invalid toToken address "${toToken}"`);
594
325
  }
595
326
  if (!Number.isFinite(amount) || amount <= 0) {
596
327
  throw new StableValidationError("amount", amount, "LI.FI bridge: amount must be a finite positive number");
597
328
  }
598
- if (recipient !== void 0 && !isAddress2(recipient)) {
329
+ if (recipient !== void 0 && !isAddress(recipient)) {
599
330
  throw new StableValidationError("recipient", recipient, `LI.FI bridge: invalid recipient address "${recipient}"`);
600
331
  }
601
332
  if (fromChain === toChain) {
@@ -683,10 +414,10 @@ var LiFiService = class {
683
414
  });
684
415
  }
685
416
  const srcChain = makeChain(srcChainId, srcRpc);
686
- const wc = this.config.walletClient ?? createWalletClient2({
417
+ const wc = this.config.walletClient ?? createWalletClient({
687
418
  account: this.config.account,
688
419
  chain: srcChain,
689
- transport: this.config.transport ?? http2(srcRpc)
420
+ transport: this.config.transport ?? http(srcRpc)
690
421
  });
691
422
  try {
692
423
  await wc.switchChain({ id: srcChainId });
@@ -723,10 +454,10 @@ var LiFiService = class {
723
454
  const tokenAddr = quote.fromToken;
724
455
  const isNative = tokenAddr.toLowerCase() === "0x0000000000000000000000000000000000000000" || tokenAddr.toLowerCase() === "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
725
456
  if (isNative || !quote.approvalAddress) return;
726
- const pc = createPublicClient2({ chain: srcChain, transport: http2(srcRpc) });
457
+ const pc = createPublicClient({ chain: srcChain, transport: http(srcRpc) });
727
458
  const allowance = await pc.readContract({
728
459
  address: tokenAddr,
729
- abi: erc20Abi2,
460
+ abi: erc20Abi,
730
461
  functionName: "allowance",
731
462
  args: [from, quote.approvalAddress]
732
463
  });
@@ -735,7 +466,7 @@ var LiFiService = class {
735
466
  try {
736
467
  approveHash = await wc.writeContract({
737
468
  address: tokenAddr,
738
- abi: erc20Abi2,
469
+ abi: erc20Abi,
739
470
  functionName: "approve",
740
471
  args: [quote.approvalAddress, quote.fromAmount],
741
472
  account: wc.account,
@@ -772,19 +503,14 @@ function isLiFiQuoteShape(v) {
772
503
  }
773
504
 
774
505
  // src/stable.ts
775
- function isUsdt0Route(fromChain, toChain, fromToken, toToken) {
776
- const src = BRIDGE_CHAIN_CONFIGS[fromChain];
777
- const dst = BRIDGE_CHAIN_CONFIGS[toChain];
778
- return !!src && !!dst && src.lzOutbound !== false && src.usdt.toLowerCase() === fromToken.toLowerCase() && dst.usdt.toLowerCase() === toToken.toLowerCase();
779
- }
780
506
  function validateTransferParams({ to, amount, token, tokenDecimals }) {
781
- if (!isAddress3(to)) {
507
+ if (!isAddress2(to)) {
782
508
  throw new StableValidationError("to", to, `transfer: invalid recipient address "${to}"`);
783
509
  }
784
510
  if (!Number.isFinite(amount) || amount <= 0) {
785
511
  throw new StableValidationError("amount", amount, "transfer: amount must be a finite positive number");
786
512
  }
787
- if (token !== void 0 && !isAddress3(token)) {
513
+ if (token !== void 0 && !isAddress2(token)) {
788
514
  throw new StableValidationError("token", token, `transfer: invalid token address "${token}"`);
789
515
  }
790
516
  if (tokenDecimals !== void 0 && (!Number.isInteger(tokenDecimals) || tokenDecimals < 0 || tokenDecimals > 77)) {
@@ -794,7 +520,7 @@ function validateTransferParams({ to, amount, token, tokenDecimals }) {
794
520
  async function resolveTokenDecimals(publicClient, token, tokenDecimals) {
795
521
  if (tokenDecimals !== void 0) return tokenDecimals;
796
522
  try {
797
- return await publicClient.readContract({ address: token, abi: erc20Abi3, functionName: "decimals" });
523
+ return await publicClient.readContract({ address: token, abi: erc20Abi2, functionName: "decimals" });
798
524
  } catch {
799
525
  throw new StableValidationError(
800
526
  "tokenDecimals",
@@ -815,9 +541,9 @@ async function executeTokenTransfer(wc, publicClient, token, to, amount, tokenDe
815
541
  const decimals = await resolveTokenDecimals(publicClient, token, tokenDecimals);
816
542
  return wc.writeContract({
817
543
  address: token,
818
- abi: erc20Abi3,
544
+ abi: erc20Abi2,
819
545
  functionName: "transfer",
820
- args: [to, parseUnits3(String(amount), decimals)],
546
+ args: [to, parseUnits2(String(amount), decimals)],
821
547
  account: acc,
822
548
  chain
823
549
  });
@@ -832,16 +558,15 @@ function createStable({
832
558
  const chain = network === "mainnet" /* Mainnet */ ? stableMainnet : stableTestnet;
833
559
  const rpc = (rpcOverride ?? chain.rpcUrls.default.http[0]).replace(/\/$/, "");
834
560
  const signerConfig = { account, transport, walletClient };
835
- const lz = new LayerZeroService(signerConfig);
836
561
  const lifi = new LiFiService({ ...signerConfig, rpc, chainId: chain.id });
837
562
  async function transfer(params) {
838
563
  validateTransferParams(params);
839
564
  const { from, to, amount, token, tokenDecimals } = params;
840
565
  const acc = walletClient?.account ?? account ?? from;
841
- const wc = walletClient ?? createWalletClient3({
566
+ const wc = walletClient ?? createWalletClient2({
842
567
  account: acc,
843
568
  chain,
844
- transport: transport ?? http3(rpc)
569
+ transport: transport ?? http2(rpc)
845
570
  });
846
571
  try {
847
572
  await wc.switchChain({ id: chain.id });
@@ -853,8 +578,8 @@ function createStable({
853
578
  cause: err
854
579
  });
855
580
  }
856
- const publicClient = createPublicClient3({ chain, transport: http3(rpc) });
857
- const hash = token !== void 0 ? await executeTokenTransfer(wc, publicClient, token, to, amount, tokenDecimals, acc, chain) : await wc.sendTransaction({ account: acc, chain, to, value: parseUnits3(String(amount), 18) });
581
+ const publicClient = createPublicClient2({ chain, transport: http2(rpc) });
582
+ const hash = token !== void 0 ? await executeTokenTransfer(wc, publicClient, token, to, amount, tokenDecimals, acc, chain) : await wc.sendTransaction({ account: acc, chain, to, value: parseUnits2(String(amount), 18) });
858
583
  const receipt = await publicClient.waitForTransactionReceipt({ hash });
859
584
  if (receipt.status === "reverted") {
860
585
  throw new StableTransactionError({
@@ -867,10 +592,10 @@ function createStable({
867
592
  return { txHash: receipt.transactionHash };
868
593
  }
869
594
  function quoteBridge(params) {
870
- return isUsdt0Route(params.fromChain, params.toChain, params.fromToken, params.toToken) ? lz.quoteBridge(params) : lifi.quoteBridge(params);
595
+ return lifi.quoteBridge(params);
871
596
  }
872
597
  function bridge(params) {
873
- return isUsdt0Route(params.fromChain, params.toChain, params.fromToken, params.toToken) ? lz.bridge(params) : lifi.bridge(params);
598
+ return lifi.bridge(params);
874
599
  }
875
600
  return {
876
601
  transfer,
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@stablechain/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Stable SDK",
5
5
  "keywords": ["stable", "usdt", "gasless", "web3"],
6
6
  "license": "MIT",
7
7
  "private": false,
8
8
  "publishConfig": {
9
- "access": "public"
9
+ "access": "public",
10
+ "provenance": true
10
11
  },
11
12
  "type": "module",
12
13
  "main": "dist/index.cjs",
@@ -29,7 +30,9 @@
29
30
  "format": "biome check --apply .",
30
31
  "clean": "rimraf dist",
31
32
  "build": "tsup --splitting",
32
- "prepublishOnly": "bun run build"
33
+ "prepublishOnly": "bun run build",
34
+ "test": "vitest run",
35
+ "test:watch": "vitest"
33
36
  },
34
37
  "peerDependencies": {
35
38
  "viem": ">=2.0.0"
@@ -37,6 +40,7 @@
37
40
  "devDependencies": {
38
41
  "tsup": "^8.0.2",
39
42
  "typescript": "^5",
40
- "viem": "^2.0.0"
43
+ "viem": "^2.0.0",
44
+ "vitest": "^2.0.0"
41
45
  }
42
46
  }