@augustdigital/sdk 8.0.0 → 8.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -26,3 +26,4 @@ export * from './MultiAssetNativeDepositWrapper';
26
26
  export * from './TokenizedVaultV2SenderAllocationWhitelist';
27
27
  export * from './RwaRedeemSubaccount';
28
28
  export * from './OFT';
29
+ export * from './SwapRouter';
package/lib/abis/index.js CHANGED
@@ -42,4 +42,5 @@ __exportStar(require("./MultiAssetNativeDepositWrapper"), exports);
42
42
  __exportStar(require("./TokenizedVaultV2SenderAllocationWhitelist"), exports);
43
43
  __exportStar(require("./RwaRedeemSubaccount"), exports);
44
44
  __exportStar(require("./OFT"), exports);
45
+ __exportStar(require("./SwapRouter"), exports);
45
46
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,5 @@
1
1
  import { IContractWriteOptions, INativeDepositOptions, ApproveResult } from '../../modules/vaults/write.actions';
2
+ import type { ISwapAndDepositOptions, ISwapRouterDirectDepositOptions, ISwapRouterNativeDepositOptions } from '../../types';
2
3
  import { IPreviewDepositOptions, IPreviewRedeemOptions, IAllowanceOptions, IBalanceOfOptions, IMaxDepositOptions } from '../../modules/vaults/read.actions';
3
4
  import { CompatibleSigner } from '../../core/helpers/signer';
4
5
  import { IAddress } from '../../types';
@@ -15,6 +16,9 @@ declare class EVMAdapter {
15
16
  vaultDeposit(options: IContractWriteOptions): Promise<string>;
16
17
  vaultRequestRedeem(options: IContractWriteOptions): Promise<string>;
17
18
  depositNative(options: INativeDepositOptions): Promise<string>;
19
+ swapAndDeposit(options: ISwapAndDepositOptions): Promise<string>;
20
+ depositViaSwapRouter(options: ISwapRouterDirectDepositOptions): Promise<string>;
21
+ depositNativeViaSwapRouter(options: ISwapRouterNativeDepositOptions): Promise<string>;
18
22
  vaultRedeem(options: IContractWriteOptions & {
19
23
  year: string;
20
24
  month: string;
@@ -60,6 +60,18 @@ class EVMAdapter {
60
60
  const signer = await this.getSigner();
61
61
  return (0, write_actions_1.depositNative)(signer, options);
62
62
  }
63
+ async swapAndDeposit(options) {
64
+ const signer = await this.getSigner();
65
+ return (0, write_actions_1.swapAndDeposit)(signer, options);
66
+ }
67
+ async depositViaSwapRouter(options) {
68
+ const signer = await this.getSigner();
69
+ return (0, write_actions_1.depositViaSwapRouter)(signer, options);
70
+ }
71
+ async depositNativeViaSwapRouter(options) {
72
+ const signer = await this.getSigner();
73
+ return (0, write_actions_1.depositNativeViaSwapRouter)(signer, options);
74
+ }
63
75
  async vaultRedeem(options) {
64
76
  const signer = await this.getSigner();
65
77
  return (0, write_actions_1.vaultRedeem)(signer, options);
@@ -65,6 +65,9 @@ exports.METHOD_CATEGORIES = {
65
65
  maxDeposit: 'read.vault',
66
66
  vaultDeposit: 'write.deposit',
67
67
  depositNative: 'write.deposit',
68
+ swapAndDeposit: 'write.deposit',
69
+ depositViaSwapRouter: 'write.deposit',
70
+ depositNativeViaSwapRouter: 'write.deposit',
68
71
  vaultRedeem: 'write.redeem',
69
72
  vaultRequestRedeem: 'write.redeem',
70
73
  rwaRedeemAsset: 'write.redeem',
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "8.0.0";
1
+ export declare const SDK_VERSION = "8.2.0";
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SDK_VERSION = void 0;
4
- exports.SDK_VERSION = '8.0.0';
4
+ exports.SDK_VERSION = '8.2.0';
5
5
  //# sourceMappingURL=version.js.map
@@ -0,0 +1,8 @@
1
+ import { IAddress } from '../../types';
2
+ export declare const SWAP_ROUTER_ADDRESSES: Readonly<Record<number, IAddress>>;
3
+ export declare const VAULTS_USING_SWAP_ROUTER: ReadonlySet<string>;
4
+ export declare const ORIGIN_CODES: {
5
+ readonly default: `0x${string}`;
6
+ };
7
+ export declare const SWAP_ROUTER_MAX_SWAPS = 9;
8
+ export declare const SWAP_ROUTER_WRAPPED_NATIVE: Readonly<Record<number, IAddress>>;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SWAP_ROUTER_WRAPPED_NATIVE = exports.SWAP_ROUTER_MAX_SWAPS = exports.ORIGIN_CODES = exports.VAULTS_USING_SWAP_ROUTER = exports.SWAP_ROUTER_ADDRESSES = void 0;
4
+ exports.SWAP_ROUTER_ADDRESSES = {
5
+ 1: '0xAC771209FF2b71EECfF6E85a9AD01db8Ff2618B0',
6
+ };
7
+ exports.VAULTS_USING_SWAP_ROUTER = new Set([
8
+ '0xe9b725010a9e419412ed67d0fa5f3a5f40159d32',
9
+ '0x74ad2f789ed583dbd141bbdafc673fe1f033718b',
10
+ ]);
11
+ exports.ORIGIN_CODES = {
12
+ default: '0x0000000000000000000000000000000000000000000000000000000000000000',
13
+ };
14
+ exports.SWAP_ROUTER_MAX_SWAPS = 9;
15
+ exports.SWAP_ROUTER_WRAPPED_NATIVE = {
16
+ 1: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
17
+ };
18
+ //# sourceMappingURL=swap-router.js.map
@@ -0,0 +1,4 @@
1
+ import { IAddress } from '../../types';
2
+ export declare function getSwapRouterAddress(chainId: number): IAddress | undefined;
3
+ export declare function vaultUsesSwapRouter(vaultAddress: IAddress): boolean;
4
+ export declare function resolveOriginCode(provided?: `0x${string}`): `0x${string}`;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSwapRouterAddress = getSwapRouterAddress;
4
+ exports.vaultUsesSwapRouter = vaultUsesSwapRouter;
5
+ exports.resolveOriginCode = resolveOriginCode;
6
+ const swap_router_1 = require("../constants/swap-router");
7
+ const errors_1 = require("../errors");
8
+ function getSwapRouterAddress(chainId) {
9
+ return swap_router_1.SWAP_ROUTER_ADDRESSES[chainId];
10
+ }
11
+ function vaultUsesSwapRouter(vaultAddress) {
12
+ return swap_router_1.VAULTS_USING_SWAP_ROUTER.has(vaultAddress.toLowerCase());
13
+ }
14
+ function resolveOriginCode(provided) {
15
+ if (provided === undefined)
16
+ return swap_router_1.ORIGIN_CODES.default;
17
+ if (!/^0x[0-9a-fA-F]{64}$/.test(provided)) {
18
+ throw new errors_1.AugustValidationError('INVALID_INPUT', `resolveOriginCode: originCode must be a 32-byte hex string (66 chars incl. 0x), got "${provided}" (${provided.length} chars)`, { context: { provided, expectedLength: 66 } });
19
+ }
20
+ return provided;
21
+ }
22
+ //# sourceMappingURL=swap-router.js.map
@@ -9,8 +9,10 @@ export * from './constants/adapters';
9
9
  export * from './constants/core';
10
10
  export * from './constants/web3';
11
11
  export * from './constants/vaults';
12
+ export * from './constants/swap-router';
12
13
  export * from './helpers/web3';
13
14
  export * from './helpers/vaults';
14
15
  export * from './helpers/core';
15
16
  export * from './helpers/adapters';
16
17
  export * from './helpers/signer';
18
+ export * from './helpers/swap-router';
package/lib/core/index.js CHANGED
@@ -25,9 +25,11 @@ __exportStar(require("./constants/adapters"), exports);
25
25
  __exportStar(require("./constants/core"), exports);
26
26
  __exportStar(require("./constants/web3"), exports);
27
27
  __exportStar(require("./constants/vaults"), exports);
28
+ __exportStar(require("./constants/swap-router"), exports);
28
29
  __exportStar(require("./helpers/web3"), exports);
29
30
  __exportStar(require("./helpers/vaults"), exports);
30
31
  __exportStar(require("./helpers/core"), exports);
31
32
  __exportStar(require("./helpers/adapters"), exports);
32
33
  __exportStar(require("./helpers/signer"), exports);
34
+ __exportStar(require("./helpers/swap-router"), exports);
33
35
  //# sourceMappingURL=index.js.map
package/lib/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from './types';
3
3
  export * from './core';
4
4
  export * from './abis';
5
5
  export * from './services/debank';
6
+ export * from './services/swap-quotes';
6
7
  export * from './modules/vaults';
7
8
  export * from './modules/sub-accounts';
8
9
  export * from './evm';
package/lib/index.js CHANGED
@@ -20,6 +20,7 @@ __exportStar(require("./types"), exports);
20
20
  __exportStar(require("./core"), exports);
21
21
  __exportStar(require("./abis"), exports);
22
22
  __exportStar(require("./services/debank"), exports);
23
+ __exportStar(require("./services/swap-quotes"), exports);
23
24
  __exportStar(require("./modules/vaults"), exports);
24
25
  __exportStar(require("./modules/sub-accounts"), exports);
25
26
  __exportStar(require("./evm"), exports);
@@ -1,5 +1,6 @@
1
1
  import { Signer, Wallet, TransactionResponse } from 'ethers';
2
2
  import { IAddress } from '../../types';
3
+ import type { ISwapAndDepositOptions, ISwapRouterDirectDepositOptions, ISwapRouterNativeDepositOptions } from '../../types';
3
4
  export type IContractWriteOptions = {
4
5
  target: IAddress;
5
6
  wallet: IAddress;
@@ -10,6 +11,8 @@ export type IContractWriteOptions = {
10
11
  poolName?: string;
11
12
  isInstantRedeem?: boolean;
12
13
  isDepositWithPermit?: boolean;
14
+ receiver?: IAddress;
15
+ slippageBps?: number;
13
16
  };
14
17
  export type INativeDepositOptions = {
15
18
  wrapperAddress: IAddress;
@@ -31,6 +34,7 @@ export declare function resolveSpender(args: {
31
34
  isMultiAssetVault: boolean;
32
35
  isAdapterDeposit: boolean;
33
36
  adapterWrapperAddress?: IAddress;
37
+ swapRouterAddress?: IAddress;
34
38
  }): IAddress;
35
39
  export declare function validateAmountPrecision(amount: string | bigint | number): void;
36
40
  export declare function isNonceParsing(error: unknown): boolean;
@@ -71,3 +75,6 @@ export type IRwaRedeemOptions = {
71
75
  wait?: boolean;
72
76
  };
73
77
  export declare function rwaRedeemAsset(signer: Signer | Wallet, options: IRwaRedeemOptions): Promise<string>;
78
+ export declare function swapAndDeposit(signer: Signer | Wallet, options: ISwapAndDepositOptions): Promise<string>;
79
+ export declare function depositViaSwapRouter(signer: Signer | Wallet, options: ISwapRouterDirectDepositOptions): Promise<string>;
80
+ export declare function depositNativeViaSwapRouter(signer: Signer | Wallet, options: ISwapRouterNativeDepositOptions): Promise<string>;
@@ -15,9 +15,13 @@ exports.vaultRequestRedeem = vaultRequestRedeem;
15
15
  exports.vaultRedeem = vaultRedeem;
16
16
  exports.depositNative = depositNative;
17
17
  exports.rwaRedeemAsset = rwaRedeemAsset;
18
+ exports.swapAndDeposit = swapAndDeposit;
19
+ exports.depositViaSwapRouter = depositViaSwapRouter;
20
+ exports.depositNativeViaSwapRouter = depositNativeViaSwapRouter;
18
21
  const ethers_1 = require("ethers");
19
22
  const abis_1 = require("../../abis");
20
23
  const core_1 = require("../../core");
24
+ const swap_quotes_1 = require("../../services/swap-quotes");
21
25
  const adapter_helpers_1 = require("./adapter.helpers");
22
26
  const utils_1 = require("./utils");
23
27
  function safeBigInt(value, context = 'safeBigInt') {
@@ -50,6 +54,8 @@ async function resolveDepositTokenDecimals(args) {
50
54
  return readErc20Decimals(actualDepositAsset);
51
55
  }
52
56
  function resolveSpender(args) {
57
+ if (args.swapRouterAddress)
58
+ return args.swapRouterAddress;
53
59
  if (args.isMultiAssetVault)
54
60
  return args.target;
55
61
  if (args.isAdapterDeposit && args.adapterWrapperAddress)
@@ -202,11 +208,16 @@ async function approveCore(signer, options) {
202
208
  if (isNativeToken)
203
209
  return { kind: 'native' };
204
210
  const isAdapterDeposit = actualDepositAsset.toLowerCase() !== underlyingAsset.toLowerCase();
211
+ const resolvedChainId = options.chainId ?? tokenizedVault?.chain;
212
+ const swapRouterAddress = resolvedChainId !== undefined && (0, core_1.vaultUsesSwapRouter)(target)
213
+ ? (0, core_1.getSwapRouterAddress)(resolvedChainId)
214
+ : undefined;
205
215
  const spenderAddress = resolveSpender({
206
216
  target,
207
217
  isMultiAssetVault,
208
218
  isAdapterDeposit,
209
219
  adapterWrapperAddress: adapterConfig?.wrapperAddress,
220
+ swapRouterAddress,
210
221
  });
211
222
  const depositTokenDecimals = await resolveDepositTokenDecimals({
212
223
  actualDepositAsset,
@@ -318,7 +329,23 @@ async function vaultDeposit(signer, options) {
318
329
  actualDepositAsset === '0x0000000000000000000000000000000000000000';
319
330
  const isAdapterDeposit = actualDepositAsset.toLowerCase() !== underlyingAsset.toLowerCase();
320
331
  const isMultiAssetVault = vaultVersion === 'evm-2';
321
- if (isAdapterDeposit && !isMultiAssetVault && !adapterConfig) {
332
+ const resolvedChainId = chainId ?? tokenizedVault?.chain;
333
+ const wantsSwapRouter = (0, core_1.vaultUsesSwapRouter)(target);
334
+ const swapRouterAddress = wantsSwapRouter && resolvedChainId !== undefined
335
+ ? (0, core_1.getSwapRouterAddress)(resolvedChainId)
336
+ : undefined;
337
+ if (wantsSwapRouter && !swapRouterAddress) {
338
+ throw new core_1.AugustValidationError('INVALID_CHAIN', resolvedChainId === undefined
339
+ ? `vaultDeposit: vault ${target} requires SwapRouter routing but chainId could not be resolved — pass options.chainId or ensure tokenized-vault metadata is loaded`
340
+ : `vaultDeposit: vault ${target} is registered on SwapRouter but no SwapRouter is deployed for chainId ${resolvedChainId}`, { context: { vault: target, chainId: resolvedChainId } });
341
+ }
342
+ if (wantsSwapRouter && options?.isDepositWithPermit) {
343
+ throw new core_1.AugustValidationError('INVALID_INPUT', `vaultDeposit: isDepositWithPermit is not supported on SwapRouter-routed vaults (${target}). Call vaultDeposit without isDepositWithPermit, or use the legacy vault.deposit path directly.`, { context: { vault: target } });
344
+ }
345
+ if (isAdapterDeposit &&
346
+ !isMultiAssetVault &&
347
+ !adapterConfig &&
348
+ !swapRouterAddress) {
322
349
  throw new core_1.AugustValidationError('INVALID_INPUT', `vaultDeposit: depositAsset ${actualDepositAsset} differs from vault underlying ${underlyingAsset} but no adapter is configured for vault ${target}`);
323
350
  }
324
351
  const depositTokenDecimals = await resolveDepositTokenDecimals({
@@ -337,6 +364,23 @@ async function vaultDeposit(signer, options) {
337
364
  },
338
365
  });
339
366
  const normalizedAmt = (0, core_1.toNormalizedBn)(amount, depositTokenDecimals);
367
+ if (swapRouterAddress && resolvedChainId !== undefined) {
368
+ return dispatchViaSwapRouter({
369
+ signer,
370
+ routerAddress: swapRouterAddress,
371
+ chainId: resolvedChainId,
372
+ target,
373
+ wallet,
374
+ receiver: options.receiver,
375
+ actualDepositAsset,
376
+ underlyingAsset,
377
+ isNativeToken,
378
+ depositTokenDecimals,
379
+ normalizedAmt,
380
+ slippageBps: options.slippageBps,
381
+ wait,
382
+ });
383
+ }
340
384
  if (!isNativeToken) {
341
385
  const spenderAddress = resolveSpender({
342
386
  target,
@@ -666,4 +710,219 @@ async function rwaRedeemAsset(signer, options) {
666
710
  throw new core_1.AugustSDKError('UNKNOWN', `RWA redeem failed: ${e instanceof Error ? e.message : 'Unknown error'}`, { cause: e, context: { target, asset, amount, minOut } });
667
711
  }
668
712
  }
713
+ async function dispatchViaSwapRouter(args) {
714
+ const amountRaw = BigInt(args.normalizedAmt.raw);
715
+ const sharesReceiver = args.receiver ?? args.wallet;
716
+ if (args.isNativeToken) {
717
+ const wrappedNative = core_1.SWAP_ROUTER_WRAPPED_NATIVE[args.chainId];
718
+ if (!wrappedNative ||
719
+ args.underlyingAsset.toLowerCase() !== wrappedNative.toLowerCase()) {
720
+ throw new core_1.AugustValidationError('INVALID_INPUT', `vaultDeposit (SwapRouter): native deposit is only supported when the vault's reference asset is the chain's wrapped-native token. Vault ${args.target} underlying ${args.underlyingAsset} is not. Wrap to ${wrappedNative ?? 'WETH'} first and call again with depositAsset = the wrapped token.`, {
721
+ context: {
722
+ vault: args.target,
723
+ underlying: args.underlyingAsset,
724
+ chainId: args.chainId,
725
+ wrappedNative,
726
+ },
727
+ });
728
+ }
729
+ return depositNativeViaSwapRouter(args.signer, {
730
+ chainId: args.chainId,
731
+ vault: args.target,
732
+ receiver: sharesReceiver,
733
+ amount: amountRaw,
734
+ wait: args.wait,
735
+ });
736
+ }
737
+ const isUnderlying = args.actualDepositAsset.toLowerCase() ===
738
+ args.underlyingAsset.toLowerCase();
739
+ if (isUnderlying) {
740
+ return depositViaSwapRouter(args.signer, {
741
+ chainId: args.chainId,
742
+ vault: args.target,
743
+ receiver: sharesReceiver,
744
+ asset: args.actualDepositAsset,
745
+ amount: amountRaw,
746
+ wait: args.wait,
747
+ });
748
+ }
749
+ const underlyingErc20 = (0, core_1.createContract)({
750
+ address: args.underlyingAsset,
751
+ provider: args.signer,
752
+ abi: abis_1.ABI_ERC20,
753
+ });
754
+ const underlyingDecimals = Number(await underlyingErc20.decimals());
755
+ const quote = await (0, swap_quotes_1.fetchSwapQuote)({
756
+ chainId: args.chainId,
757
+ srcToken: args.actualDepositAsset,
758
+ srcDecimals: args.depositTokenDecimals,
759
+ destToken: args.underlyingAsset,
760
+ destDecimals: underlyingDecimals,
761
+ amount: amountRaw,
762
+ receiver: args.routerAddress,
763
+ slippageBps: args.slippageBps,
764
+ });
765
+ return swapAndDeposit(args.signer, {
766
+ chainId: args.chainId,
767
+ vault: args.target,
768
+ receiver: sharesReceiver,
769
+ swaps: [
770
+ {
771
+ tokenIn: args.actualDepositAsset,
772
+ tokenOut: args.underlyingAsset,
773
+ amountIn: amountRaw,
774
+ minAmountOut: quote.minAmountOut,
775
+ router: quote.router,
776
+ payload: quote.payload,
777
+ },
778
+ ],
779
+ wait: args.wait,
780
+ });
781
+ }
782
+ function resolveSwapRouterOrThrow(chainId) {
783
+ const router = (0, core_1.getSwapRouterAddress)(chainId);
784
+ if (!router) {
785
+ throw new core_1.AugustValidationError('INVALID_CHAIN', `SwapRouter: no deployment registered for chainId ${chainId}`, { context: { chainId } });
786
+ }
787
+ return router;
788
+ }
789
+ async function ensureAllowance(signer, token, owner, spender, amount) {
790
+ const tokenContract = (0, core_1.createContract)({
791
+ address: token,
792
+ provider: signer,
793
+ abi: abis_1.ABI_ERC20,
794
+ });
795
+ const current = safeBigInt(await tokenContract.allowance(owner, spender), 'swapRouter:allowance');
796
+ if (current >= amount)
797
+ return;
798
+ const { hash } = await safeSendTx(() => tokenContract.connect(signer).approve(spender, amount), signer, true);
799
+ core_1.Logger.log.info('swapRouter:approve:tx_hash', hash);
800
+ }
801
+ function ensureSwapsValid(swaps) {
802
+ if (swaps.length === 0) {
803
+ throw new core_1.AugustValidationError('INVALID_INPUT', 'swapAndDeposit: at least one swap leg is required');
804
+ }
805
+ if (swaps.length > core_1.SWAP_ROUTER_MAX_SWAPS) {
806
+ throw new core_1.AugustValidationError('INVALID_INPUT', `swapAndDeposit: too many swaps (${swaps.length} > ${core_1.SWAP_ROUTER_MAX_SWAPS})`, { context: { count: swaps.length, max: core_1.SWAP_ROUTER_MAX_SWAPS } });
807
+ }
808
+ for (let i = 0; i < swaps.length; i += 1) {
809
+ validateSwapParams(swaps[i], i);
810
+ }
811
+ }
812
+ function validateSwapParams(swap, index) {
813
+ const where = `swapAndDeposit: swaps[${index}]`;
814
+ if (!(0, core_1.checkAddress)(swap.tokenIn, console, 'contract')) {
815
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', `${where}.tokenIn is not a valid address`);
816
+ }
817
+ if (!(0, core_1.checkAddress)(swap.tokenOut, console, 'contract')) {
818
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', `${where}.tokenOut is not a valid address`);
819
+ }
820
+ if (!(0, core_1.checkAddress)(swap.router, console, 'contract')) {
821
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', `${where}.router is not a valid address`);
822
+ }
823
+ if (swap.tokenIn.toLowerCase() === swap.tokenOut.toLowerCase()) {
824
+ throw new core_1.AugustValidationError('INVALID_INPUT', `${where}: tokenIn and tokenOut are identical — no swap needed`);
825
+ }
826
+ if (swap.amountIn <= 0n) {
827
+ throw new core_1.AugustValidationError('INVALID_INPUT', `${where}.amountIn must be greater than zero`);
828
+ }
829
+ if (swap.minAmountOut <= 0n) {
830
+ throw new core_1.AugustValidationError('INVALID_INPUT', `${where}.minAmountOut must be greater than zero — slippage protection cannot be disabled`);
831
+ }
832
+ if (!/^0x[0-9a-fA-F]+$/.test(swap.payload) || swap.payload.length < 10) {
833
+ throw new core_1.AugustValidationError('INVALID_INPUT', `${where}.payload must be ABI-encoded calldata (got "${swap.payload.slice(0, 12)}…")`);
834
+ }
835
+ }
836
+ function totalInputPerToken(swaps) {
837
+ const totals = new Map();
838
+ for (const swap of swaps) {
839
+ const key = swap.tokenIn.toLowerCase();
840
+ totals.set(key, (totals.get(key) ?? 0n) + swap.amountIn);
841
+ }
842
+ return totals;
843
+ }
844
+ async function resolveSignerEOA(signer, callerContext) {
845
+ const getAddress = signer.getAddress;
846
+ if (typeof getAddress !== 'function') {
847
+ throw new core_1.AugustValidationError('INVALID_INPUT', `${callerContext}: signer must implement getAddress(); got ${typeof getAddress}`);
848
+ }
849
+ const eoa = await getAddress.call(signer);
850
+ if (!eoa || !(0, core_1.checkAddress)(eoa, console, 'wallet')) {
851
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', `${callerContext}: signer.getAddress() returned an invalid address: ${String(eoa)}`);
852
+ }
853
+ return eoa;
854
+ }
855
+ async function swapAndDeposit(signer, options) {
856
+ const { chainId, vault, receiver, swaps, originCode, wait } = options;
857
+ const goodVault = (0, core_1.checkAddress)(vault, console, 'contract');
858
+ const goodReceiver = (0, core_1.checkAddress)(receiver, console, 'wallet');
859
+ if (!goodVault || !goodReceiver) {
860
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', `swapAndDeposit: invalid ${!goodVault ? 'vault' : 'receiver'} address`);
861
+ }
862
+ ensureSwapsValid(swaps);
863
+ const routerAddress = resolveSwapRouterOrThrow(chainId);
864
+ const eoa = await resolveSignerEOA(signer, 'swapAndDeposit');
865
+ for (const [tokenIn, totalIn] of totalInputPerToken(swaps)) {
866
+ await ensureAllowance(signer, tokenIn, eoa, routerAddress, totalIn);
867
+ }
868
+ const routerContract = (0, core_1.createContract)({
869
+ address: routerAddress,
870
+ provider: signer,
871
+ abi: abis_1.ABI_SWAP_ROUTER,
872
+ });
873
+ const { hash } = await safeSendTx(() => routerContract
874
+ .connect(signer)
875
+ .swapAndDeposit((0, core_1.resolveOriginCode)(originCode), vault, receiver, swaps), signer, wait);
876
+ core_1.Logger.log.info('swapAndDeposit:tx_hash', hash);
877
+ return hash;
878
+ }
879
+ async function depositViaSwapRouter(signer, options) {
880
+ const { chainId, vault, receiver, asset, amount, originCode, wait } = options;
881
+ const goodVault = (0, core_1.checkAddress)(vault, console, 'contract');
882
+ const goodReceiver = (0, core_1.checkAddress)(receiver, console, 'wallet');
883
+ const goodAsset = (0, core_1.checkAddress)(asset, console, 'contract');
884
+ if (!goodVault || !goodReceiver || !goodAsset) {
885
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', 'depositViaSwapRouter: invalid address');
886
+ }
887
+ if (amount === 0n) {
888
+ throw new core_1.AugustValidationError('INVALID_INPUT', 'depositViaSwapRouter: amount must be greater than zero');
889
+ }
890
+ const routerAddress = resolveSwapRouterOrThrow(chainId);
891
+ const eoa = await resolveSignerEOA(signer, 'depositViaSwapRouter');
892
+ await ensureAllowance(signer, asset, eoa, routerAddress, amount);
893
+ const routerContract = (0, core_1.createContract)({
894
+ address: routerAddress,
895
+ provider: signer,
896
+ abi: abis_1.ABI_SWAP_ROUTER,
897
+ });
898
+ const { hash } = await safeSendTx(() => routerContract
899
+ .connect(signer)
900
+ .deposit((0, core_1.resolveOriginCode)(originCode), amount, vault, asset, receiver), signer, wait);
901
+ core_1.Logger.log.info('depositViaSwapRouter:tx_hash', hash);
902
+ return hash;
903
+ }
904
+ async function depositNativeViaSwapRouter(signer, options) {
905
+ const { chainId, vault, receiver, amount, originCode, wait } = options;
906
+ const goodVault = (0, core_1.checkAddress)(vault, console, 'contract');
907
+ const goodReceiver = (0, core_1.checkAddress)(receiver, console, 'wallet');
908
+ if (!goodVault || !goodReceiver) {
909
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', 'depositNativeViaSwapRouter: invalid address');
910
+ }
911
+ if (amount === 0n) {
912
+ throw new core_1.AugustValidationError('INVALID_INPUT', 'depositNativeViaSwapRouter: amount must be greater than zero');
913
+ }
914
+ const routerAddress = resolveSwapRouterOrThrow(chainId);
915
+ const routerContract = (0, core_1.createContract)({
916
+ address: routerAddress,
917
+ provider: signer,
918
+ abi: abis_1.ABI_SWAP_ROUTER,
919
+ });
920
+ const { hash } = await safeSendTx(() => routerContract
921
+ .connect(signer)
922
+ .depositNativeToken((0, core_1.resolveOriginCode)(originCode), vault, receiver, {
923
+ value: amount,
924
+ }), signer, wait);
925
+ core_1.Logger.log.info('depositNativeViaSwapRouter:tx_hash', hash);
926
+ return hash;
927
+ }
669
928
  //# sourceMappingURL=write.actions.js.map
@@ -0,0 +1,25 @@
1
+ import type { IAddress } from '../../types';
2
+ export type ISwapQuoteProvider = 'paraswap';
3
+ export interface ISwapQuoteRequest {
4
+ chainId: number;
5
+ srcToken: IAddress;
6
+ srcDecimals: number;
7
+ destToken: IAddress;
8
+ destDecimals: number;
9
+ amount: bigint;
10
+ receiver: IAddress;
11
+ slippageBps?: number;
12
+ partner?: string;
13
+ partnerAddress?: IAddress;
14
+ fetchImpl?: typeof fetch;
15
+ signal?: AbortSignal;
16
+ }
17
+ export type ISwapQuoteResult = {
18
+ provider: 'paraswap';
19
+ router: IAddress;
20
+ payload: `0x${string}`;
21
+ expectedAmountOut: bigint;
22
+ minAmountOut: bigint;
23
+ fetchedAt: number;
24
+ };
25
+ export declare function fetchSwapQuote(request: ISwapQuoteRequest): Promise<ISwapQuoteResult>;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchSwapQuote = fetchSwapQuote;
4
+ const errors_1 = require("../../core/errors");
5
+ const paraswap_1 = require("./paraswap");
6
+ const DEFAULT_SLIPPAGE_BPS = 100;
7
+ const BPS_DENOMINATOR = 10000n;
8
+ async function fetchSwapQuote(request) {
9
+ validateRequest(request);
10
+ const slippageBps = request.slippageBps ?? DEFAULT_SLIPPAGE_BPS;
11
+ const fetchImpl = request.fetchImpl ?? globalThis.fetch;
12
+ const { router, payload, expectedAmountOut, fetchedAt } = await (0, paraswap_1.fetchParaswapQuote)({
13
+ chainId: request.chainId,
14
+ srcToken: request.srcToken,
15
+ srcDecimals: request.srcDecimals,
16
+ destToken: request.destToken,
17
+ destDecimals: request.destDecimals,
18
+ amount: request.amount,
19
+ receiver: request.receiver,
20
+ slippageBps,
21
+ partner: request.partner ?? paraswap_1.PARASWAP_DEFAULTS.partner,
22
+ partnerAddress: request.partnerAddress ?? paraswap_1.PARASWAP_DEFAULTS.partnerAddress,
23
+ fetchImpl,
24
+ signal: request.signal,
25
+ });
26
+ const minAmountOut = applySlippage(expectedAmountOut, slippageBps);
27
+ return {
28
+ provider: 'paraswap',
29
+ router,
30
+ payload,
31
+ expectedAmountOut,
32
+ minAmountOut,
33
+ fetchedAt,
34
+ };
35
+ }
36
+ function validateRequest(req) {
37
+ if (req.slippageBps !== undefined &&
38
+ (req.slippageBps < 0 || req.slippageBps >= 10000)) {
39
+ throw new errors_1.AugustValidationError('INVALID_INPUT', `fetchSwapQuote: slippageBps must be in [0, 10000), got ${req.slippageBps}. 10000 bps = 100% slippage and disables protection entirely; use a tighter bound.`);
40
+ }
41
+ if (req.amount === 0n) {
42
+ throw new errors_1.AugustValidationError('INVALID_INPUT', 'fetchSwapQuote: amount must be greater than zero');
43
+ }
44
+ if (req.srcToken.toLowerCase() === req.destToken.toLowerCase()) {
45
+ throw new errors_1.AugustValidationError('INVALID_INPUT', 'fetchSwapQuote: srcToken and destToken are identical — no swap needed');
46
+ }
47
+ }
48
+ function applySlippage(amount, slippageBps) {
49
+ return (amount * (BPS_DENOMINATOR - BigInt(slippageBps))) / BPS_DENOMINATOR;
50
+ }
51
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,26 @@
1
+ import type { IAddress } from '../../types';
2
+ export interface IParaswapQuoteInput {
3
+ chainId: number;
4
+ srcToken: IAddress;
5
+ srcDecimals: number;
6
+ destToken: IAddress;
7
+ destDecimals: number;
8
+ amount: bigint;
9
+ receiver: IAddress;
10
+ slippageBps: number;
11
+ partner: string;
12
+ partnerAddress: IAddress;
13
+ fetchImpl: typeof fetch;
14
+ signal?: AbortSignal;
15
+ }
16
+ export interface IParaswapQuoteOutput {
17
+ router: IAddress;
18
+ payload: `0x${string}`;
19
+ expectedAmountOut: bigint;
20
+ fetchedAt: number;
21
+ }
22
+ export declare function fetchParaswapQuote(input: IParaswapQuoteInput): Promise<IParaswapQuoteOutput>;
23
+ export declare const PARASWAP_DEFAULTS: {
24
+ readonly partner: "august";
25
+ readonly partnerAddress: `0x${string}`;
26
+ };