@whiterresearch/litvmswap-aggregator 1.0.4

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/client.js ADDED
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LitVMAggregator = void 0;
4
+ const viem_1 = require("viem");
5
+ const index_js_1 = require("./constants/index.js");
6
+ const quoter_js_1 = require("./quoter/quoter.js");
7
+ const swapBuilder_js_1 = require("./swap/swapBuilder.js");
8
+ const index_js_2 = require("./abi/index.js");
9
+ /**
10
+ * Main SDK Client for LitecoinVM (LitVM) DEX Aggregator
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * import { LitVMAggregator } from '@whiterresearch/litvmswap-aggregator';
15
+ *
16
+ * const aggregator = new LitVMAggregator();
17
+ *
18
+ * // 1. Get best quote across LitVM liquidity pools
19
+ * const quote = await aggregator.getQuote({
20
+ * tokenIn: 'zkLTC',
21
+ * tokenOut: 'ZKUSDC',
22
+ * amountIn: '1.0',
23
+ * slippageTolerancePercent: 0.5,
24
+ * });
25
+ *
26
+ * // 2. Build ready-to-execute swap transaction
27
+ * const tx = aggregator.buildSwapTx({
28
+ * quote,
29
+ * userAddress: '0x1234...',
30
+ * });
31
+ * ```
32
+ */
33
+ class LitVMAggregator {
34
+ quoter;
35
+ publicClient;
36
+ defaultFeeConfig;
37
+ constructor(config) {
38
+ this.publicClient =
39
+ config?.publicClient ??
40
+ (0, viem_1.createPublicClient)({
41
+ chain: index_js_1.LitVMChain,
42
+ transport: (0, viem_1.http)(config?.rpcUrl ?? index_js_1.LitVMChain.rpcUrls.default.http[0]),
43
+ });
44
+ this.quoter = new quoter_js_1.LitVMQuoter(this.publicClient);
45
+ this.defaultFeeConfig = config?.defaultFeeConfig;
46
+ }
47
+ /**
48
+ * Fetches best quote and generates execution program across LitVM pools
49
+ */
50
+ async getQuote(params) {
51
+ return this.quoter.getQuote(params);
52
+ }
53
+ /**
54
+ * Prepares a ready-to-sign transaction object (to, data, value, chainId)
55
+ */
56
+ buildSwapTx(params) {
57
+ const feeConfig = params.feeConfig ?? this.defaultFeeConfig;
58
+ return swapBuilder_js_1.LitVMSwapBuilder.buildSwapTransaction({
59
+ ...params,
60
+ feeConfig,
61
+ });
62
+ }
63
+ /**
64
+ * Checks ERC20 token allowance for a given spender (defaults to Aggregator Entrypoint)
65
+ */
66
+ async checkAllowance(params) {
67
+ const spender = params.spenderAddress ?? index_js_1.LITVM_ADDRESSES.aggregatorEntrypoint;
68
+ const allowance = await this.publicClient.readContract({
69
+ address: params.tokenAddress,
70
+ abi: index_js_2.ERC20ABI,
71
+ functionName: 'allowance',
72
+ args: [params.ownerAddress, spender],
73
+ });
74
+ return allowance;
75
+ }
76
+ /**
77
+ * Checks if an ERC20 token needs approval for a swap
78
+ */
79
+ async needsApproval(params) {
80
+ if (params.tokenAddress === viem_1.zeroAddress)
81
+ return false;
82
+ const currentAllowance = await this.checkAllowance(params);
83
+ return currentAllowance < params.amount;
84
+ }
85
+ /**
86
+ * Generates ERC20 approval transaction data
87
+ */
88
+ buildApproveTx(params) {
89
+ return swapBuilder_js_1.LitVMSwapBuilder.buildApproveTransaction(params.tokenAddress, params.spenderAddress ?? index_js_1.LITVM_ADDRESSES.aggregatorEntrypoint, params.amount);
90
+ }
91
+ /**
92
+ * Resolves token metadata from address or symbol
93
+ */
94
+ async getToken(addressOrSymbol) {
95
+ return this.quoter.resolveToken(addressOrSymbol);
96
+ }
97
+ /**
98
+ * Returns list of verified tokens on LitecoinVM
99
+ */
100
+ getKnownTokens() {
101
+ return Object.values(index_js_1.KNOWN_TOKENS);
102
+ }
103
+ /**
104
+ * Directly executes a swap using a Viem WalletClient
105
+ */
106
+ async executeSwapWithWallet(params) {
107
+ const tx = this.buildSwapTx({
108
+ quote: params.quote,
109
+ userAddress: params.userAddress,
110
+ receiverAddress: params.receiverAddress,
111
+ feeConfig: params.feeConfig,
112
+ });
113
+ const hash = await params.walletClient.sendTransaction({
114
+ account: params.userAddress,
115
+ to: tx.to,
116
+ data: tx.data,
117
+ value: tx.value,
118
+ chain: index_js_1.LitVMChain,
119
+ });
120
+ return hash;
121
+ }
122
+ }
123
+ exports.LitVMAggregator = LitVMAggregator;
@@ -0,0 +1,67 @@
1
+ import type { Chain } from 'viem';
2
+ export declare const LITECOIN_VM_CHAIN_ID = 4441;
3
+ /**
4
+ * Viem Chain definition for LitecoinVM (LitVM)
5
+ */
6
+ export declare const LitVMChain: Chain;
7
+ /**
8
+ * Core contract addresses for the Aggregator & Liquidity Pools on LitecoinVM
9
+ */
10
+ export declare const LITVM_ADDRESSES: {
11
+ chainId: number;
12
+ aggregatorEntrypoint: "0xF664B56933f3cF0d7d69982b5A8eC9101b80059D";
13
+ /** The wrapper, named explicitly. Same address as aggregatorEntrypoint. */
14
+ pointsWrapper: "0xF664B56933f3cF0d7d69982b5A8eC9101b80059D";
15
+ /**
16
+ * The fee-enforcing entrypoint the wrapper forwards to. It requires the
17
+ * protocol fee to go to the DexFeeVault and to be at least MIN_PROTOCOL_FEE_BPS;
18
+ * a swap that does not will revert. Exposed for inspection — route through
19
+ * `aggregatorEntrypoint` so points are still recorded.
20
+ */
21
+ feeEnforcingEntrypoint: "0x5E19EB2A6BA30892CCe33f93D7Fb24D498512266";
22
+ /**
23
+ * Superseded. The original entrypoint, which took feeCollector and feeBps
24
+ * straight from calldata and enforced neither, so any caller could pay the
25
+ * protocol nothing. The wrapper no longer routes here. Kept only so an
26
+ * integrator pinning this address can see why their swaps changed.
27
+ * @deprecated use `aggregatorEntrypoint`
28
+ */
29
+ legacyEntrypointNoFeeEnforcement: "0xF69E64804000d28aA695eB5c594B996100fb3B49";
30
+ aggregatorRouter: "0x0624E93350bFfc5B3570589FCae68e2CaBe6c620";
31
+ platformFeeCollector: "0xF2DF37067a8Af0e9ae617c96C887B2FdA8eA3f10";
32
+ wrappedNative: "0x315374AA9b5536037Cc1Efeea2439CCC0913A77e";
33
+ weth: "0x315374AA9b5536037Cc1Efeea2439CCC0913A77e";
34
+ ourV2Factory: "0x4680BCe1632824d30D2F53656dD610736c3e312e";
35
+ ourV2Router: "0xF456737D17C2Bbb348fd4F7D1b000D62A46FB3b5";
36
+ inkyV2Factory: "0x458C5d5B75ccBA22651D2C5b61cB1EA1e0b0f95D";
37
+ v3Factory: "0xde6763a041f8fc94ca2ee5933736f78f6d1a11c5";
38
+ v3Router: "0x60F8A7642F0aeC06cE628224E743326B23Fe5208";
39
+ v3PositionManager: "0x1089f046B597f259BeFDC15Bf9C90E33616BA366";
40
+ };
41
+ /**
42
+ * Sentinel address for native LTC/ETH
43
+ */
44
+ /**
45
+ * Minimum protocol fee, in basis points, enforced on-chain by the entrypoint.
46
+ * A swap routed through the entrypoint with a lower fee, or with the fee pointed
47
+ * anywhere other than the DexFeeVault, reverts.
48
+ */
49
+ export declare const MIN_PROTOCOL_FEE_BPS = 15n;
50
+ export declare const NATIVE_TOKEN_ADDRESS: "0x0000000000000000000000000000000000000000";
51
+ export declare const NATIVE_TOKEN_ALT_ADDRESS: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
52
+ export interface TokenInfo {
53
+ address: `0x${string}`;
54
+ symbol: string;
55
+ name: string;
56
+ decimals: number;
57
+ isNative?: boolean;
58
+ logoURI?: string;
59
+ }
60
+ /**
61
+ * Native zkLTC definition
62
+ */
63
+ export declare const NATIVE_TOKEN: TokenInfo;
64
+ /**
65
+ * Standard tokens deployed on LitecoinVM (Chain ID 4441)
66
+ */
67
+ export declare const KNOWN_TOKENS: Record<string, TokenInfo>;
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KNOWN_TOKENS = exports.NATIVE_TOKEN = exports.NATIVE_TOKEN_ALT_ADDRESS = exports.NATIVE_TOKEN_ADDRESS = exports.MIN_PROTOCOL_FEE_BPS = exports.LITVM_ADDRESSES = exports.LitVMChain = exports.LITECOIN_VM_CHAIN_ID = void 0;
4
+ exports.LITECOIN_VM_CHAIN_ID = 4441;
5
+ /**
6
+ * Viem Chain definition for LitecoinVM (LitVM)
7
+ */
8
+ exports.LitVMChain = {
9
+ id: exports.LITECOIN_VM_CHAIN_ID,
10
+ name: 'LitecoinVM',
11
+ nativeCurrency: {
12
+ name: 'zkLTC',
13
+ symbol: 'zkLTC',
14
+ decimals: 18,
15
+ },
16
+ rpcUrls: {
17
+ default: {
18
+ http: [
19
+ 'https://liteforge.rpc.caldera.xyz/http',
20
+ 'https://liteforge.rpc.caldera.xyz/infra-partner-http',
21
+ ],
22
+ },
23
+ public: {
24
+ http: [
25
+ 'https://liteforge.rpc.caldera.xyz/http',
26
+ 'https://liteforge.rpc.caldera.xyz/infra-partner-http',
27
+ ],
28
+ },
29
+ },
30
+ blockExplorers: {
31
+ default: {
32
+ name: 'LitVM Explorer',
33
+ url: 'https://explorer.LitVM.network',
34
+ },
35
+ },
36
+ testnet: true,
37
+ };
38
+ /**
39
+ * Core contract addresses for the Aggregator & Liquidity Pools on LitecoinVM
40
+ */
41
+ exports.LITVM_ADDRESSES = {
42
+ chainId: exports.LITECOIN_VM_CHAIN_ID,
43
+ // ── Aggregator contracts ──────────────────────────────────────────────
44
+ // Swaps should go to `aggregatorEntrypoint` — the AGGFlowPointsWrapper. It
45
+ // records Lit Diamonds and applies the NFT staking multiplier, then forwards
46
+ // to the fee-enforcing entrypoint. Calling anything below it skips the points
47
+ // a user has earned.
48
+ aggregatorEntrypoint: '0xF664B56933f3cF0d7d69982b5A8eC9101b80059D',
49
+ /** The wrapper, named explicitly. Same address as aggregatorEntrypoint. */
50
+ pointsWrapper: '0xF664B56933f3cF0d7d69982b5A8eC9101b80059D',
51
+ /**
52
+ * The fee-enforcing entrypoint the wrapper forwards to. It requires the
53
+ * protocol fee to go to the DexFeeVault and to be at least MIN_PROTOCOL_FEE_BPS;
54
+ * a swap that does not will revert. Exposed for inspection — route through
55
+ * `aggregatorEntrypoint` so points are still recorded.
56
+ */
57
+ feeEnforcingEntrypoint: '0x5E19EB2A6BA30892CCe33f93D7Fb24D498512266',
58
+ /**
59
+ * Superseded. The original entrypoint, which took feeCollector and feeBps
60
+ * straight from calldata and enforced neither, so any caller could pay the
61
+ * protocol nothing. The wrapper no longer routes here. Kept only so an
62
+ * integrator pinning this address can see why their swaps changed.
63
+ * @deprecated use `aggregatorEntrypoint`
64
+ */
65
+ legacyEntrypointNoFeeEnforcement: '0xF69E64804000d28aA695eB5c594B996100fb3B49',
66
+ aggregatorRouter: '0x0624E93350bFfc5B3570589FCae68e2CaBe6c620',
67
+ platformFeeCollector: '0xF2DF37067a8Af0e9ae617c96C887B2FdA8eA3f10',
68
+ // Wrapped Native (wzkLTC / WETH)
69
+ wrappedNative: '0x315374AA9b5536037Cc1Efeea2439CCC0913A77e',
70
+ weth: '0x315374AA9b5536037Cc1Efeea2439CCC0913A77e',
71
+ // Uniswap V2 Compatible DEXes
72
+ ourV2Factory: '0x4680BCe1632824d30D2F53656dD610736c3e312e',
73
+ ourV2Router: '0xF456737D17C2Bbb348fd4F7D1b000D62A46FB3b5',
74
+ inkyV2Factory: '0x458C5d5B75ccBA22651D2C5b61cB1EA1e0b0f95D',
75
+ // Uniswap V3 Compatible DEXes
76
+ v3Factory: '0xde6763a041f8fc94ca2ee5933736f78f6d1a11c5',
77
+ v3Router: '0x60F8A7642F0aeC06cE628224E743326B23Fe5208',
78
+ v3PositionManager: '0x1089f046B597f259BeFDC15Bf9C90E33616BA366',
79
+ };
80
+ /**
81
+ * Sentinel address for native LTC/ETH
82
+ */
83
+ /**
84
+ * Minimum protocol fee, in basis points, enforced on-chain by the entrypoint.
85
+ * A swap routed through the entrypoint with a lower fee, or with the fee pointed
86
+ * anywhere other than the DexFeeVault, reverts.
87
+ */
88
+ exports.MIN_PROTOCOL_FEE_BPS = 15n; // 0.15%
89
+ exports.NATIVE_TOKEN_ADDRESS = '0x0000000000000000000000000000000000000000';
90
+ exports.NATIVE_TOKEN_ALT_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
91
+ /**
92
+ * Native zkLTC definition
93
+ */
94
+ exports.NATIVE_TOKEN = {
95
+ address: exports.NATIVE_TOKEN_ADDRESS,
96
+ symbol: 'zkLTC',
97
+ name: 'Litecoin (zkLTC)',
98
+ decimals: 18,
99
+ isNative: true,
100
+ logoURI: 'https://assets.coingecko.com/coins/images/2/standard/litecoin.png',
101
+ };
102
+ /**
103
+ * Standard tokens deployed on LitecoinVM (Chain ID 4441)
104
+ */
105
+ exports.KNOWN_TOKENS = {
106
+ NATIVE: exports.NATIVE_TOKEN,
107
+ WZKLTC: {
108
+ address: '0x315374AA9b5536037Cc1Efeea2439CCC0913A77e',
109
+ symbol: 'wzkLTC',
110
+ name: 'Wrapped zkLTC',
111
+ decimals: 18,
112
+ isNative: false,
113
+ logoURI: 'https://assets.coingecko.com/coins/images/2/standard/litecoin.png',
114
+ },
115
+ ZKUSDC: {
116
+ address: '0xdf69970B2fE416339187aA41D39882e864984CE9',
117
+ symbol: 'ZKUSDC',
118
+ name: 'ZK USD Coin',
119
+ decimals: 18,
120
+ isNative: false,
121
+ logoURI: 'https://assets.coingecko.com/coins/images/53776/standard/usdc.jpg',
122
+ },
123
+ ZKUSDT: {
124
+ address: '0xa338b743Ec494ebB8345f4B6F27ffC902b7EF5Aa',
125
+ symbol: 'ZKUSDT',
126
+ name: 'ZK Tether USD',
127
+ decimals: 18,
128
+ isNative: false,
129
+ logoURI: 'https://assets.coingecko.com/coins/images/53705/standard/usdt0.jpg',
130
+ },
131
+ LETH: {
132
+ address: '0xDF474006aa807598B616500d146FfF661d644138',
133
+ symbol: 'LETH',
134
+ name: 'LitVM Ethereum',
135
+ decimals: 18,
136
+ isNative: false,
137
+ logoURI: 'https://assets.coingecko.com/coins/images/279/standard/ethereum.png',
138
+ },
139
+ ZKBTC: {
140
+ address: '0xca4914407868bc37ccbE324cA149DD475d39A2Bf',
141
+ symbol: 'ZKBTC',
142
+ name: 'ZK Bitcoin',
143
+ decimals: 18,
144
+ isNative: false,
145
+ logoURI: 'https://assets.coingecko.com/coins/images/1/standard/bitcoin.png',
146
+ },
147
+ LITVMSWAP: {
148
+ address: '0xCa4c7EdB398684cB4C5B3fD0cc6ced30b5a5f4d3',
149
+ symbol: 'LitVMSwap',
150
+ name: 'LitVMSwap Token',
151
+ decimals: 18,
152
+ isNative: false,
153
+ },
154
+ LXRP: {
155
+ address: '0xfdf5cD6452EDC340e67cd16db6A9D74aaa4f81a3',
156
+ symbol: 'LXRP',
157
+ name: 'LitVM XRP',
158
+ decimals: 18,
159
+ isNative: false,
160
+ },
161
+ BRBNB: {
162
+ address: '0x58B6CD7891cd0A682226E25607b958a6479195A6',
163
+ symbol: 'brBNB',
164
+ name: 'Bridged BNB',
165
+ decimals: 18,
166
+ isNative: false,
167
+ },
168
+ };
@@ -0,0 +1,9 @@
1
+ export { LitVMAggregator, type LitVMAggregatorConfig } from './client.js';
2
+ export { LitVMQuoter } from './quoter/quoter.js';
3
+ export { LitVMSwapBuilder } from './swap/swapBuilder.js';
4
+ export { buildAggregatorProgram, addressToBytes } from './builder/programBuilder.js';
5
+ export { OPCODES, POOL_TYPES, WRAP_FLAGS } from './builder/opcodes.js';
6
+ export { LITECOIN_VM_CHAIN_ID, LitVMChain, LITVM_ADDRESSES, MIN_PROTOCOL_FEE_BPS, NATIVE_TOKEN_ADDRESS, NATIVE_TOKEN_ALT_ADDRESS, NATIVE_TOKEN, KNOWN_TOKENS, type TokenInfo, } from './constants/index.js';
7
+ export type { PoolType, RouteLeg, QuoteParams, QuoteResult, FeeConfig, BuildSwapTxParams, PreparedTransaction, SwapIntent, FeeCollection, } from './types/index.js';
8
+ export { toBigIntAmount, formatTokenAmount, calculateMinAmountOut, calculatePriceImpact, } from './utils/format.js';
9
+ export * from './abi/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.calculatePriceImpact = exports.calculateMinAmountOut = exports.formatTokenAmount = exports.toBigIntAmount = exports.KNOWN_TOKENS = exports.NATIVE_TOKEN = exports.NATIVE_TOKEN_ALT_ADDRESS = exports.NATIVE_TOKEN_ADDRESS = exports.MIN_PROTOCOL_FEE_BPS = exports.LITVM_ADDRESSES = exports.LitVMChain = exports.LITECOIN_VM_CHAIN_ID = exports.WRAP_FLAGS = exports.POOL_TYPES = exports.OPCODES = exports.addressToBytes = exports.buildAggregatorProgram = exports.LitVMSwapBuilder = exports.LitVMQuoter = exports.LitVMAggregator = void 0;
18
+ // Main Client
19
+ var client_js_1 = require("./client.js");
20
+ Object.defineProperty(exports, "LitVMAggregator", { enumerable: true, get: function () { return client_js_1.LitVMAggregator; } });
21
+ // Quoter & Router
22
+ var quoter_js_1 = require("./quoter/quoter.js");
23
+ Object.defineProperty(exports, "LitVMQuoter", { enumerable: true, get: function () { return quoter_js_1.LitVMQuoter; } });
24
+ // Swap & Program Builders
25
+ var swapBuilder_js_1 = require("./swap/swapBuilder.js");
26
+ Object.defineProperty(exports, "LitVMSwapBuilder", { enumerable: true, get: function () { return swapBuilder_js_1.LitVMSwapBuilder; } });
27
+ var programBuilder_js_1 = require("./builder/programBuilder.js");
28
+ Object.defineProperty(exports, "buildAggregatorProgram", { enumerable: true, get: function () { return programBuilder_js_1.buildAggregatorProgram; } });
29
+ Object.defineProperty(exports, "addressToBytes", { enumerable: true, get: function () { return programBuilder_js_1.addressToBytes; } });
30
+ var opcodes_js_1 = require("./builder/opcodes.js");
31
+ Object.defineProperty(exports, "OPCODES", { enumerable: true, get: function () { return opcodes_js_1.OPCODES; } });
32
+ Object.defineProperty(exports, "POOL_TYPES", { enumerable: true, get: function () { return opcodes_js_1.POOL_TYPES; } });
33
+ Object.defineProperty(exports, "WRAP_FLAGS", { enumerable: true, get: function () { return opcodes_js_1.WRAP_FLAGS; } });
34
+ // Constants & Chain Details
35
+ var index_js_1 = require("./constants/index.js");
36
+ Object.defineProperty(exports, "LITECOIN_VM_CHAIN_ID", { enumerable: true, get: function () { return index_js_1.LITECOIN_VM_CHAIN_ID; } });
37
+ Object.defineProperty(exports, "LitVMChain", { enumerable: true, get: function () { return index_js_1.LitVMChain; } });
38
+ Object.defineProperty(exports, "LITVM_ADDRESSES", { enumerable: true, get: function () { return index_js_1.LITVM_ADDRESSES; } });
39
+ Object.defineProperty(exports, "MIN_PROTOCOL_FEE_BPS", { enumerable: true, get: function () { return index_js_1.MIN_PROTOCOL_FEE_BPS; } });
40
+ Object.defineProperty(exports, "NATIVE_TOKEN_ADDRESS", { enumerable: true, get: function () { return index_js_1.NATIVE_TOKEN_ADDRESS; } });
41
+ Object.defineProperty(exports, "NATIVE_TOKEN_ALT_ADDRESS", { enumerable: true, get: function () { return index_js_1.NATIVE_TOKEN_ALT_ADDRESS; } });
42
+ Object.defineProperty(exports, "NATIVE_TOKEN", { enumerable: true, get: function () { return index_js_1.NATIVE_TOKEN; } });
43
+ Object.defineProperty(exports, "KNOWN_TOKENS", { enumerable: true, get: function () { return index_js_1.KNOWN_TOKENS; } });
44
+ // Math & Format Utilities
45
+ var format_js_1 = require("./utils/format.js");
46
+ Object.defineProperty(exports, "toBigIntAmount", { enumerable: true, get: function () { return format_js_1.toBigIntAmount; } });
47
+ Object.defineProperty(exports, "formatTokenAmount", { enumerable: true, get: function () { return format_js_1.formatTokenAmount; } });
48
+ Object.defineProperty(exports, "calculateMinAmountOut", { enumerable: true, get: function () { return format_js_1.calculateMinAmountOut; } });
49
+ Object.defineProperty(exports, "calculatePriceImpact", { enumerable: true, get: function () { return format_js_1.calculatePriceImpact; } });
50
+ // ABIs
51
+ __exportStar(require("./abi/index.js"), exports);
@@ -0,0 +1,19 @@
1
+ import { type PublicClient } from 'viem';
2
+ import { type TokenInfo } from '../constants/index.js';
3
+ import type { QuoteParams, QuoteResult } from '../types/index.js';
4
+ export declare class LitVMQuoter {
5
+ private client;
6
+ constructor(customClient?: PublicClient);
7
+ /**
8
+ * Resolves token metadata from address or symbol
9
+ */
10
+ resolveToken(addressOrSymbol: string): Promise<TokenInfo>;
11
+ /**
12
+ * Fetches best quote and generates execution program across LitVM pools
13
+ */
14
+ getQuote(params: QuoteParams): Promise<QuoteResult>;
15
+ /**
16
+ * Helper: Quotes a Uniswap V2 pair
17
+ */
18
+ private quoteV2Pool;
19
+ }
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LitVMQuoter = void 0;
4
+ const viem_1 = require("viem");
5
+ const index_js_1 = require("../constants/index.js");
6
+ const index_js_2 = require("../abi/index.js");
7
+ const programBuilder_js_1 = require("../builder/programBuilder.js");
8
+ const format_js_1 = require("../utils/format.js");
9
+ class LitVMQuoter {
10
+ client;
11
+ constructor(customClient) {
12
+ this.client =
13
+ customClient ??
14
+ (0, viem_1.createPublicClient)({
15
+ chain: index_js_1.LitVMChain,
16
+ transport: (0, viem_1.http)(index_js_1.LitVMChain.rpcUrls.default.http[0]),
17
+ });
18
+ }
19
+ /**
20
+ * Resolves token metadata from address or symbol
21
+ */
22
+ async resolveToken(addressOrSymbol) {
23
+ const query = addressOrSymbol.trim();
24
+ // Check known native tokens
25
+ if (query === viem_1.zeroAddress ||
26
+ query.toLowerCase() === index_js_1.NATIVE_TOKEN_ALT_ADDRESS.toLowerCase() ||
27
+ query.toUpperCase() === 'ETH' ||
28
+ query.toUpperCase() === 'LTC' ||
29
+ query.toUpperCase() === 'ZKLTC') {
30
+ return index_js_1.NATIVE_TOKEN;
31
+ }
32
+ // Check predefined list
33
+ const found = Object.values(index_js_1.KNOWN_TOKENS).find((t) => t.address.toLowerCase() === query.toLowerCase() ||
34
+ t.symbol.toUpperCase() === query.toUpperCase());
35
+ if (found)
36
+ return found;
37
+ // Fetch ERC-20 on-chain details
38
+ const tokenAddr = query;
39
+ const [decimals, symbol, name] = await Promise.all([
40
+ this.client.readContract({
41
+ address: tokenAddr,
42
+ abi: index_js_2.ERC20ABI,
43
+ functionName: 'decimals',
44
+ }),
45
+ this.client.readContract({
46
+ address: tokenAddr,
47
+ abi: index_js_2.ERC20ABI,
48
+ functionName: 'symbol',
49
+ }),
50
+ this.client.readContract({
51
+ address: tokenAddr,
52
+ abi: index_js_2.ERC20ABI,
53
+ functionName: 'name',
54
+ }),
55
+ ]);
56
+ return {
57
+ address: tokenAddr,
58
+ symbol,
59
+ name,
60
+ decimals: Number(decimals),
61
+ isNative: false,
62
+ };
63
+ }
64
+ /**
65
+ * Fetches best quote and generates execution program across LitVM pools
66
+ */
67
+ async getQuote(params) {
68
+ const fromToken = await this.resolveToken(params.tokenIn);
69
+ const toToken = await this.resolveToken(params.tokenOut);
70
+ if (fromToken.address.toLowerCase() === toToken.address.toLowerCase() && fromToken.isNative === toToken.isNative) {
71
+ throw new Error('Cannot swap a token to itself');
72
+ }
73
+ const amountIn = (0, format_js_1.toBigIntAmount)(params.amountIn, fromToken.decimals);
74
+ if (amountIn <= 0n) {
75
+ throw new Error('Amount in must be greater than 0');
76
+ }
77
+ const slippage = params.slippageTolerancePercent ?? 0.5;
78
+ // Handle Wrap / Unwrap directly
79
+ const isWrap = fromToken.isNative && toToken.address.toLowerCase() === index_js_1.LITVM_ADDRESSES.weth.toLowerCase();
80
+ const isUnwrap = fromToken.address.toLowerCase() === index_js_1.LITVM_ADDRESSES.weth.toLowerCase() && toToken.isNative;
81
+ if (isWrap || isUnwrap) {
82
+ const amountOut = amountIn; // 1:1 wrap/unwrap
83
+ const route = {
84
+ dexName: isWrap ? 'NativeWrap' : 'NativeUnwrap',
85
+ poolType: 'wrap',
86
+ poolAddress: index_js_1.LITVM_ADDRESSES.weth,
87
+ tokenIn: fromToken.address,
88
+ tokenOut: toToken.address,
89
+ };
90
+ return {
91
+ tokenIn: fromToken,
92
+ tokenOut: toToken,
93
+ amountIn,
94
+ amountInFormatted: (0, format_js_1.formatTokenAmount)(amountIn, fromToken.decimals),
95
+ expectedAmountOut: amountOut,
96
+ expectedAmountOutFormatted: (0, format_js_1.formatTokenAmount)(amountOut, toToken.decimals),
97
+ minAmountOut: amountOut,
98
+ minAmountOutFormatted: (0, format_js_1.formatTokenAmount)(amountOut, toToken.decimals),
99
+ priceImpactPercent: 0,
100
+ executionPrice: 1,
101
+ route,
102
+ program: '0x',
103
+ };
104
+ }
105
+ // Resolve intermediate ERC20 addresses (if native, route via wzkLTC)
106
+ const tokenInAddr = fromToken.isNative ? index_js_1.LITVM_ADDRESSES.weth : fromToken.address;
107
+ const tokenOutAddr = toToken.isNative ? index_js_1.LITVM_ADDRESSES.weth : toToken.address;
108
+ const candidates = [];
109
+ // 1. Query OurV2 Factory
110
+ const ourV2Candidate = await this.quoteV2Pool(index_js_1.LITVM_ADDRESSES.ourV2Factory, 'OurV2', tokenInAddr, tokenOutAddr, amountIn, 3000 // 0.3% fee
111
+ );
112
+ if (ourV2Candidate)
113
+ candidates.push(ourV2Candidate);
114
+ // 2. Query InkyV2 Factory
115
+ const inkyV2Candidate = await this.quoteV2Pool(index_js_1.LITVM_ADDRESSES.inkyV2Factory, 'InkyV2', tokenInAddr, tokenOutAddr, amountIn, 3000);
116
+ if (inkyV2Candidate)
117
+ candidates.push(inkyV2Candidate);
118
+ if (candidates.length === 0) {
119
+ throw new Error(`No active liquidity pools found between ${fromToken.symbol} and ${toToken.symbol} on LitecoinVM`);
120
+ }
121
+ // Select candidate with the best amountOut
122
+ const best = candidates.reduce((a, b) => (a.amountOut > b.amountOut ? a : b));
123
+ const route = {
124
+ dexName: best.dexName,
125
+ poolType: best.poolType,
126
+ poolAddress: best.poolAddress,
127
+ tokenIn: fromToken.address,
128
+ tokenOut: toToken.address,
129
+ fee: best.fee,
130
+ };
131
+ // Compile bytecode program for AGGFlow
132
+ const program = (0, programBuilder_js_1.buildAggregatorProgram)(fromToken, toToken, route, index_js_1.LITVM_ADDRESSES.weth);
133
+ const minAmountOut = (0, format_js_1.calculateMinAmountOut)(best.amountOut, slippage);
134
+ const priceImpact = best.reserveIn && best.reserveOut
135
+ ? (0, format_js_1.calculatePriceImpact)(amountIn, best.amountOut, best.reserveIn, best.reserveOut)
136
+ : 0;
137
+ const inUnits = Number((0, format_js_1.formatTokenAmount)(amountIn, fromToken.decimals, 6));
138
+ const outUnits = Number((0, format_js_1.formatTokenAmount)(best.amountOut, toToken.decimals, 6));
139
+ const executionPrice = inUnits > 0 ? outUnits / inUnits : 0;
140
+ return {
141
+ tokenIn: fromToken,
142
+ tokenOut: toToken,
143
+ amountIn,
144
+ amountInFormatted: (0, format_js_1.formatTokenAmount)(amountIn, fromToken.decimals),
145
+ expectedAmountOut: best.amountOut,
146
+ expectedAmountOutFormatted: (0, format_js_1.formatTokenAmount)(best.amountOut, toToken.decimals),
147
+ minAmountOut,
148
+ minAmountOutFormatted: (0, format_js_1.formatTokenAmount)(minAmountOut, toToken.decimals),
149
+ priceImpactPercent: priceImpact,
150
+ executionPrice,
151
+ route,
152
+ program,
153
+ };
154
+ }
155
+ /**
156
+ * Helper: Quotes a Uniswap V2 pair
157
+ */
158
+ async quoteV2Pool(factory, dexName, tokenA, tokenB, amountIn, fee) {
159
+ try {
160
+ const pair = await this.client.readContract({
161
+ address: factory,
162
+ abi: index_js_2.UniswapV2FactoryABI,
163
+ functionName: 'getPair',
164
+ args: [tokenA, tokenB],
165
+ });
166
+ if (!pair || pair === viem_1.zeroAddress)
167
+ return null;
168
+ const [reserves, token0] = await Promise.all([
169
+ this.client.readContract({
170
+ address: pair,
171
+ abi: index_js_2.UniswapV2PairABI,
172
+ functionName: 'getReserves',
173
+ }),
174
+ this.client.readContract({
175
+ address: pair,
176
+ abi: index_js_2.UniswapV2PairABI,
177
+ functionName: 'token0',
178
+ }),
179
+ ]);
180
+ const isToken0 = tokenA.toLowerCase() === token0.toLowerCase();
181
+ const reserveIn = isToken0 ? BigInt(reserves[0]) : BigInt(reserves[1]);
182
+ const reserveOut = isToken0 ? BigInt(reserves[1]) : BigInt(reserves[0]);
183
+ if (reserveIn === 0n || reserveOut === 0n)
184
+ return null;
185
+ // Constant-product AMM with fee in ppm (parts per million: 1,000,000)
186
+ // e.g. 3000 fee = 0.3%
187
+ const amountInWithFee = amountIn * BigInt(1_000_000 - fee);
188
+ const numerator = amountInWithFee * reserveOut;
189
+ const denominator = reserveIn * 1000000n + amountInWithFee;
190
+ const amountOut = numerator / denominator;
191
+ return {
192
+ dexName,
193
+ poolType: 'v2',
194
+ poolAddress: pair,
195
+ amountOut,
196
+ fee,
197
+ reserveIn,
198
+ reserveOut,
199
+ };
200
+ }
201
+ catch {
202
+ return null;
203
+ }
204
+ }
205
+ }
206
+ exports.LitVMQuoter = LitVMQuoter;
@@ -0,0 +1,15 @@
1
+ import { type Address } from 'viem';
2
+ import type { BuildSwapTxParams, PreparedTransaction } from '../types/index.js';
3
+ export declare class LitVMSwapBuilder {
4
+ /**
5
+ * Prepares a ready-to-sign transaction for executing a swap
6
+ */
7
+ static buildSwapTransaction(params: BuildSwapTxParams): PreparedTransaction;
8
+ /**
9
+ * Prepares an ERC-20 approval transaction
10
+ * @param tokenAddress The ERC-20 token contract
11
+ * @param spender The contract to approve (Defaults to AGGFlowEntrypoint)
12
+ * @param amount Optional amount to approve (defaults to max uint256)
13
+ */
14
+ static buildApproveTransaction(tokenAddress: Address, spender?: Address, amount?: bigint): PreparedTransaction;
15
+ }