@reptilianhq/uniswap-sdk 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +4 -0
  3. package/README.md +176 -0
  4. package/RELEASING.md +114 -0
  5. package/dist/abis.d.ts +161 -0
  6. package/dist/abis.d.ts.map +1 -0
  7. package/dist/abis.js +21 -0
  8. package/dist/abis.js.map +1 -0
  9. package/dist/batch.d.ts +60 -0
  10. package/dist/batch.d.ts.map +1 -0
  11. package/dist/batch.js +157 -0
  12. package/dist/batch.js.map +1 -0
  13. package/dist/compatibility.d.ts +15 -0
  14. package/dist/compatibility.d.ts.map +1 -0
  15. package/dist/compatibility.js +57 -0
  16. package/dist/compatibility.js.map +1 -0
  17. package/dist/deployments.d.ts +27 -0
  18. package/dist/deployments.d.ts.map +1 -0
  19. package/dist/deployments.js +70 -0
  20. package/dist/deployments.js.map +1 -0
  21. package/dist/depth.d.ts +24 -0
  22. package/dist/depth.d.ts.map +1 -0
  23. package/dist/depth.js +65 -0
  24. package/dist/depth.js.map +1 -0
  25. package/dist/errors.d.ts +25 -0
  26. package/dist/errors.d.ts.map +1 -0
  27. package/dist/errors.js +32 -0
  28. package/dist/errors.js.map +1 -0
  29. package/dist/events.d.ts +23 -0
  30. package/dist/events.d.ts.map +1 -0
  31. package/dist/events.js +27 -0
  32. package/dist/events.js.map +1 -0
  33. package/dist/index.d.ts +4 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +4 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/official-sdk.cjs +9 -0
  38. package/dist/official-sdk.cjs.map +1 -0
  39. package/dist/official-sdk.d.cts +2 -0
  40. package/dist/official-sdk.d.cts.map +1 -0
  41. package/dist/pool.d.ts +30 -0
  42. package/dist/pool.d.ts.map +1 -0
  43. package/dist/pool.js +55 -0
  44. package/dist/pool.js.map +1 -0
  45. package/dist/providers.d.ts +59 -0
  46. package/dist/providers.d.ts.map +1 -0
  47. package/dist/providers.js +110 -0
  48. package/dist/providers.js.map +1 -0
  49. package/dist/reads.d.ts +61 -0
  50. package/dist/reads.d.ts.map +1 -0
  51. package/dist/reads.js +92 -0
  52. package/dist/reads.js.map +1 -0
  53. package/dist/receipts.d.ts +2 -0
  54. package/dist/receipts.d.ts.map +1 -0
  55. package/dist/receipts.js +2 -0
  56. package/dist/receipts.js.map +1 -0
  57. package/dist/transactions.d.ts +2 -0
  58. package/dist/transactions.d.ts.map +1 -0
  59. package/dist/transactions.js +2 -0
  60. package/dist/transactions.js.map +1 -0
  61. package/dist/v3-abis.d.ts +525 -0
  62. package/dist/v3-abis.d.ts.map +1 -0
  63. package/dist/v3-abis.js +43 -0
  64. package/dist/v3-abis.js.map +1 -0
  65. package/dist/v3-receipts.d.ts +28 -0
  66. package/dist/v3-receipts.d.ts.map +1 -0
  67. package/dist/v3-receipts.js +68 -0
  68. package/dist/v3-receipts.js.map +1 -0
  69. package/dist/v3-transactions.d.ts +107 -0
  70. package/dist/v3-transactions.d.ts.map +1 -0
  71. package/dist/v3-transactions.js +323 -0
  72. package/dist/v3-transactions.js.map +1 -0
  73. package/dist/v3.d.ts +6 -0
  74. package/dist/v3.d.ts.map +1 -0
  75. package/dist/v3.js +6 -0
  76. package/dist/v3.js.map +1 -0
  77. package/dist/v4.d.ts +8 -0
  78. package/dist/v4.d.ts.map +1 -0
  79. package/dist/v4.js +5 -0
  80. package/dist/v4.js.map +1 -0
  81. package/docs/FORK_TESTING.md +24 -0
  82. package/examples/read-only-consumer.mjs +59 -0
  83. package/fixtures/receipts/robinhood-mainnet-v3-lifecycle.json +84 -0
  84. package/fixtures/receipts/robinhood-mainnet-v3-mint.json +42 -0
  85. package/package.json +124 -0
  86. package/provenance/mainnet.json +33 -0
  87. package/provenance/testnet.json +33 -0
  88. package/scripts/check-conformance.mjs +191 -0
  89. package/scripts/verify-v3-deployments.mjs +23 -0
package/dist/batch.js ADDED
@@ -0,0 +1,157 @@
1
+ import { decodeFunctionResult, encodeFunctionData } from 'viem';
2
+ import { v4QuoterAbi, v4StateViewAbi } from './abis.js';
3
+ import { invalid, UniswapSdkError } from './errors.js';
4
+ import { checkedAddress, validatePoolKey } from './pool.js';
5
+ import { ticksInWord } from './depth.js';
6
+ function checkedPoolId(poolId) {
7
+ if (!/^0x[0-9a-fA-F]{64}$/.test(poolId))
8
+ invalid('poolId must be bytes32');
9
+ return poolId;
10
+ }
11
+ async function batch(transport, calls) {
12
+ if (calls.length === 0)
13
+ return [];
14
+ const results = await transport(calls);
15
+ if (results.length !== calls.length)
16
+ throw new UniswapSdkError('RPC_ERROR', 'Batch response count does not match the request');
17
+ return results;
18
+ }
19
+ /** Slot0 then liquidity; callers may combine these with other venues in one RPC. */
20
+ export function v4PoolStateCalls(stateView, poolId) {
21
+ const target = checkedAddress(stateView);
22
+ const args = [checkedPoolId(poolId)];
23
+ return [
24
+ { target, allowFailure: false, callData: encodeFunctionData({ abi: v4StateViewAbi, functionName: 'getSlot0', args }) },
25
+ { target, allowFailure: false, callData: encodeFunctionData({ abi: v4StateViewAbi, functionName: 'getLiquidity', args }) },
26
+ ];
27
+ }
28
+ /** Zero state is valid for the bot's uninitialized-pool probes. */
29
+ export function decodeV4PoolState(results) {
30
+ if (results.length !== 2 || results.some(result => !result.success))
31
+ throw new UniswapSdkError('RPC_ERROR', 'Both pool state observations are required');
32
+ try {
33
+ const slot = decodeFunctionResult({ abi: v4StateViewAbi, functionName: 'getSlot0', data: results[0].returnData });
34
+ const liquidity = decodeFunctionResult({ abi: v4StateViewAbi, functionName: 'getLiquidity', data: results[1].returnData });
35
+ return { sqrtPriceX96: slot[0], tick: slot[1], protocolFee: slot[2], lpFee: slot[3], liquidity };
36
+ }
37
+ catch (cause) {
38
+ throw new UniswapSdkError('RPC_ERROR', 'Pool state response cannot be decoded', { cause });
39
+ }
40
+ }
41
+ export async function readV4PoolStatesWithBatch(transport, stateView, poolIds) {
42
+ const states = [];
43
+ for (let offset = 0; offset < poolIds.length; offset += 256) {
44
+ const ids = poolIds.slice(offset, offset + 256);
45
+ const results = await batch(transport, ids.flatMap(id => v4PoolStateCalls(stateView, id)));
46
+ states.push(...ids.map((_, i) => decodeV4PoolState(results.slice(i * 2, i * 2 + 2))));
47
+ }
48
+ return states;
49
+ }
50
+ /** Explicit multicall opt-in: hooks see the host's multicall/Quoter context. */
51
+ export async function quoteV4WithBatch(transport, quoter, inputKey, inputs) {
52
+ const key = validatePoolKey(inputKey);
53
+ const target = checkedAddress(quoter);
54
+ const calls = inputs.map(input => {
55
+ const currencyIn = checkedAddress(input.currencyIn);
56
+ if (currencyIn !== key.currency0 && currencyIn !== key.currency1)
57
+ invalid('Input currency does not belong to this pool');
58
+ // Zero input was historically accepted by the bot's sizing probes.
59
+ if (typeof input.amountIn !== 'bigint' || input.amountIn < 0n || input.amountIn >= 1n << 128n)
60
+ invalid('amountIn must be uint128');
61
+ if (typeof input.hookData !== 'string' || !/^0x(?:[0-9a-fA-F]{2})*$/.test(input.hookData))
62
+ invalid('hookData must be explicit even-length hex bytes');
63
+ return { target, allowFailure: true, callData: encodeFunctionData({ abi: v4QuoterAbi, functionName: 'quoteExactInputSingle', args: [{ poolKey: key, zeroForOne: currencyIn === key.currency0, exactAmount: input.amountIn, hookData: input.hookData }] }) };
64
+ });
65
+ const quotes = [];
66
+ for (let offset = 0; offset < calls.length; offset += 256) {
67
+ const results = await batch(transport, calls.slice(offset, offset + 256));
68
+ quotes.push(...results.map((result) => {
69
+ if (!result.success)
70
+ return { status: 'failure', error: new UniswapSdkError('QUOTE_FAILED', 'Quoter simulation reverted') };
71
+ try {
72
+ const [amountOut, gasEstimate] = decodeFunctionResult({ abi: v4QuoterAbi, functionName: 'quoteExactInputSingle', data: result.returnData });
73
+ return { status: 'success', amountOut, gasEstimate };
74
+ }
75
+ catch (cause) {
76
+ return { status: 'failure', error: new UniswapSdkError('QUOTE_FAILED', 'Quoter response cannot be decoded', { cause }) };
77
+ }
78
+ }));
79
+ }
80
+ return quotes;
81
+ }
82
+ export const V4_MIN_TICK = -887272;
83
+ export const V4_MAX_TICK = 887272;
84
+ export function usableV4TickRange(tickSpacing) {
85
+ if (!Number.isInteger(tickSpacing) || tickSpacing < 1 || tickSpacing > 32767)
86
+ invalid('tickSpacing must be between 1 and 32767');
87
+ return { min: Math.ceil(V4_MIN_TICK / tickSpacing) * tickSpacing, max: Math.floor(V4_MAX_TICK / tickSpacing) * tickSpacing };
88
+ }
89
+ export function v4WordPosition(tick, tickSpacing) {
90
+ usableV4TickRange(tickSpacing);
91
+ if (!Number.isInteger(tick))
92
+ invalid('tick must be an integer');
93
+ return Math.floor(Math.floor(tick / tickSpacing) / 256);
94
+ }
95
+ /** Spot window plus the two extremes, retaining full-range LP boundary ticks. */
96
+ export function v4DepthWordPositions(currentTick, tickSpacing, radius) {
97
+ if (!Number.isSafeInteger(radius) || radius < 0)
98
+ invalid('radius must be a nonnegative safe integer');
99
+ const { min, max } = usableV4TickRange(tickSpacing);
100
+ const lo = v4WordPosition(min, tickSpacing);
101
+ const hi = v4WordPosition(max, tickSpacing);
102
+ const centre = v4WordPosition(currentTick, tickSpacing);
103
+ const words = new Set([lo, hi]);
104
+ const start = Math.max(lo, centre - radius);
105
+ const end = Math.min(hi, centre + radius);
106
+ if (end - start + 1 > 257)
107
+ invalid('Tick scan window must contain at most 257 bitmap words');
108
+ for (let word = start; word <= end; word++)
109
+ words.add(word);
110
+ return [...words].sort((a, b) => a - b);
111
+ }
112
+ export async function readV4TicksWithBatch(transport, stateView, poolId, tickSpacing, words) {
113
+ const target = checkedAddress(stateView);
114
+ checkedPoolId(poolId);
115
+ const { min, max } = usableV4TickRange(tickSpacing);
116
+ const lo = v4WordPosition(min, tickSpacing);
117
+ const hi = v4WordPosition(max, tickSpacing);
118
+ const unique = [...new Set(words)].sort((a, b) => a - b);
119
+ if (unique.length > 259 || unique.some(word => !Number.isInteger(word) || word < lo || word > hi))
120
+ invalid('Tick scan must contain at most 259 usable bitmap words');
121
+ const bitmaps = await batch(transport, unique.map(word => ({ target, allowFailure: true, callData: encodeFunctionData({ abi: v4StateViewAbi, functionName: 'getTickBitmap', args: [poolId, word] }) })));
122
+ const failedWords = [];
123
+ const failedTicks = [];
124
+ const coordinates = [];
125
+ bitmaps.forEach((result, i) => {
126
+ if (!result.success) {
127
+ failedWords.push(unique[i]);
128
+ return;
129
+ }
130
+ try {
131
+ coordinates.push(...ticksInWord(unique[i], decodeFunctionResult({ abi: v4StateViewAbi, functionName: 'getTickBitmap', data: result.returnData }), tickSpacing));
132
+ }
133
+ catch {
134
+ failedWords.push(unique[i]);
135
+ }
136
+ });
137
+ const ticks = [];
138
+ for (let offset = 0; offset < coordinates.length; offset += 256) {
139
+ const chunk = coordinates.slice(offset, offset + 256);
140
+ const results = await batch(transport, chunk.map(tick => ({ target, allowFailure: true, callData: encodeFunctionData({ abi: v4StateViewAbi, functionName: 'getTickLiquidity', args: [poolId, tick] }) })));
141
+ results.forEach((result, i) => {
142
+ if (!result.success) {
143
+ failedTicks.push(chunk[i]);
144
+ return;
145
+ }
146
+ try {
147
+ const [liquidityGross, liquidityNet] = decodeFunctionResult({ abi: v4StateViewAbi, functionName: 'getTickLiquidity', data: result.returnData });
148
+ ticks.push({ tick: chunk[i], liquidityGross, liquidityNet });
149
+ }
150
+ catch {
151
+ failedTicks.push(chunk[i]);
152
+ }
153
+ });
154
+ }
155
+ return { ticks, failedWords, failedTicks, partial: unique.length < hi - lo + 1 || failedWords.length > 0 || failedTicks.length > 0 };
156
+ }
157
+ //# sourceMappingURL=batch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.js","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"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","sourcesContent":["import { decodeFunctionResult, encodeFunctionData, type Address, type Hex } from 'viem';\nimport { v4QuoterAbi, v4StateViewAbi } from './abis.js';\nimport { invalid, UniswapSdkError } from './errors.js';\nimport { checkedAddress, validatePoolKey, type V4PoolKey } from './pool.js';\nimport { ticksInWord } from './depth.js';\n\n/** Host-owned batch transport. Host owns chain/wiring checks, block pinning and sender. */\nexport interface V4BatchCall { target: Address; allowFailure: boolean; callData: Hex }\nexport interface V4BatchResult { success: boolean; returnData: Hex }\nexport type V4BatchTransport = (calls: V4BatchCall[]) => Promise<readonly V4BatchResult[]>;\nexport interface V4PoolState { sqrtPriceX96: bigint; tick: number; protocolFee: number; lpFee: number; liquidity: bigint }\nexport type V4BatchQuote = { status: 'success'; amountOut: bigint; gasEstimate: bigint } | { status: 'failure'; error: UniswapSdkError };\n\nfunction checkedPoolId(poolId: Hex): Hex {\n if (!/^0x[0-9a-fA-F]{64}$/.test(poolId)) invalid('poolId must be bytes32');\n return poolId;\n}\n\nasync function batch(transport: V4BatchTransport, calls: V4BatchCall[]) {\n if (calls.length === 0) return [];\n const results = await transport(calls);\n if (results.length !== calls.length) throw new UniswapSdkError('RPC_ERROR', 'Batch response count does not match the request');\n return results;\n}\n\n/** Slot0 then liquidity; callers may combine these with other venues in one RPC. */\nexport function v4PoolStateCalls(stateView: Address, poolId: Hex): [V4BatchCall, V4BatchCall] {\n const target = checkedAddress(stateView);\n const args = [checkedPoolId(poolId)] as const;\n return [\n { target, allowFailure: false, callData: encodeFunctionData({ abi: v4StateViewAbi, functionName: 'getSlot0', args }) },\n { target, allowFailure: false, callData: encodeFunctionData({ abi: v4StateViewAbi, functionName: 'getLiquidity', args }) },\n ];\n}\n\n/** Zero state is valid for the bot's uninitialized-pool probes. */\nexport function decodeV4PoolState(results: readonly V4BatchResult[]): V4PoolState {\n if (results.length !== 2 || results.some(result => !result.success)) throw new UniswapSdkError('RPC_ERROR', 'Both pool state observations are required');\n try {\n const slot = decodeFunctionResult({ abi: v4StateViewAbi, functionName: 'getSlot0', data: results[0].returnData });\n const liquidity = decodeFunctionResult({ abi: v4StateViewAbi, functionName: 'getLiquidity', data: results[1].returnData });\n return { sqrtPriceX96: slot[0], tick: slot[1], protocolFee: slot[2], lpFee: slot[3], liquidity };\n } catch (cause) { throw new UniswapSdkError('RPC_ERROR', 'Pool state response cannot be decoded', { cause }); }\n}\n\nexport async function readV4PoolStatesWithBatch(transport: V4BatchTransport, stateView: Address, poolIds: readonly Hex[]): Promise<V4PoolState[]> {\n const states: V4PoolState[] = [];\n for (let offset = 0; offset < poolIds.length; offset += 256) {\n const ids = poolIds.slice(offset, offset + 256);\n const results = await batch(transport, ids.flatMap(id => v4PoolStateCalls(stateView, id)));\n states.push(...ids.map((_, i) => decodeV4PoolState(results.slice(i * 2, i * 2 + 2))));\n }\n return states;\n}\n\n/** Explicit multicall opt-in: hooks see the host's multicall/Quoter context. */\nexport async function quoteV4WithBatch(\n transport: V4BatchTransport,\n quoter: Address,\n inputKey: V4PoolKey,\n inputs: readonly { currencyIn: Address; amountIn: bigint; hookData: Hex }[],\n): Promise<V4BatchQuote[]> {\n const key = validatePoolKey(inputKey);\n const target = checkedAddress(quoter);\n const calls = inputs.map(input => {\n const currencyIn = checkedAddress(input.currencyIn);\n if (currencyIn !== key.currency0 && currencyIn !== key.currency1) invalid('Input currency does not belong to this pool');\n // Zero input was historically accepted by the bot's sizing probes.\n if (typeof input.amountIn !== 'bigint' || input.amountIn < 0n || input.amountIn >= 1n << 128n) invalid('amountIn must be uint128');\n if (typeof input.hookData !== 'string' || !/^0x(?:[0-9a-fA-F]{2})*$/.test(input.hookData)) invalid('hookData must be explicit even-length hex bytes');\n return { target, allowFailure: true, callData: encodeFunctionData({ abi: v4QuoterAbi, functionName: 'quoteExactInputSingle', args: [{ poolKey: key, zeroForOne: currencyIn === key.currency0, exactAmount: input.amountIn, hookData: input.hookData }] }) };\n });\n const quotes: V4BatchQuote[] = [];\n for (let offset = 0; offset < calls.length; offset += 256) {\n const results = await batch(transport, calls.slice(offset, offset + 256));\n quotes.push(...results.map((result): V4BatchQuote => {\n if (!result.success) return { status: 'failure', error: new UniswapSdkError('QUOTE_FAILED', 'Quoter simulation reverted') };\n try {\n const [amountOut, gasEstimate] = decodeFunctionResult({ abi: v4QuoterAbi, functionName: 'quoteExactInputSingle', data: result.returnData });\n return { status: 'success', amountOut, gasEstimate };\n } catch (cause) { return { status: 'failure', error: new UniswapSdkError('QUOTE_FAILED', 'Quoter response cannot be decoded', { cause }) }; }\n }));\n }\n return quotes;\n}\n\nexport const V4_MIN_TICK = -887272;\nexport const V4_MAX_TICK = 887272;\nexport function usableV4TickRange(tickSpacing: number) {\n if (!Number.isInteger(tickSpacing) || tickSpacing < 1 || tickSpacing > 32767) invalid('tickSpacing must be between 1 and 32767');\n return { min: Math.ceil(V4_MIN_TICK / tickSpacing) * tickSpacing, max: Math.floor(V4_MAX_TICK / tickSpacing) * tickSpacing };\n}\nexport function v4WordPosition(tick: number, tickSpacing: number) {\n usableV4TickRange(tickSpacing);\n if (!Number.isInteger(tick)) invalid('tick must be an integer');\n return Math.floor(Math.floor(tick / tickSpacing) / 256);\n}\n/** Spot window plus the two extremes, retaining full-range LP boundary ticks. */\nexport function v4DepthWordPositions(currentTick: number, tickSpacing: number, radius: number) {\n if (!Number.isSafeInteger(radius) || radius < 0) invalid('radius must be a nonnegative safe integer');\n const { min, max } = usableV4TickRange(tickSpacing);\n const lo = v4WordPosition(min, tickSpacing);\n const hi = v4WordPosition(max, tickSpacing);\n const centre = v4WordPosition(currentTick, tickSpacing);\n const words = new Set([lo, hi]);\n const start = Math.max(lo, centre - radius);\n const end = Math.min(hi, centre + radius);\n if (end - start + 1 > 257) invalid('Tick scan window must contain at most 257 bitmap words');\n for (let word = start; word <= end; word++) words.add(word);\n return [...words].sort((a, b) => a - b);\n}\n\nexport async function readV4TicksWithBatch(transport: V4BatchTransport, stateView: Address, poolId: Hex, tickSpacing: number, words: readonly number[]) {\n const target = checkedAddress(stateView);\n checkedPoolId(poolId);\n const { min, max } = usableV4TickRange(tickSpacing);\n const lo = v4WordPosition(min, tickSpacing);\n const hi = v4WordPosition(max, tickSpacing);\n const unique = [...new Set(words)].sort((a, b) => a - b);\n if (unique.length > 259 || unique.some(word => !Number.isInteger(word) || word < lo || word > hi)) invalid('Tick scan must contain at most 259 usable bitmap words');\n const bitmaps = await batch(transport, unique.map(word => ({ target, allowFailure: true, callData: encodeFunctionData({ abi: v4StateViewAbi, functionName: 'getTickBitmap', args: [poolId, word] }) })));\n const failedWords: number[] = [];\n const failedTicks: number[] = [];\n const coordinates: number[] = [];\n bitmaps.forEach((result, i) => {\n if (!result.success) {\n failedWords.push(unique[i]);\n return;\n }\n try {\n coordinates.push(...ticksInWord(unique[i], decodeFunctionResult({ abi: v4StateViewAbi, functionName: 'getTickBitmap', data: result.returnData }), tickSpacing));\n } catch { failedWords.push(unique[i]); }\n });\n const ticks: { tick: number; liquidityGross: bigint; liquidityNet: bigint }[] = [];\n for (let offset = 0; offset < coordinates.length; offset += 256) {\n const chunk = coordinates.slice(offset, offset + 256);\n const results = await batch(transport, chunk.map(tick => ({ target, allowFailure: true, callData: encodeFunctionData({ abi: v4StateViewAbi, functionName: 'getTickLiquidity', args: [poolId, tick] }) })));\n results.forEach((result, i) => {\n if (!result.success) {\n failedTicks.push(chunk[i]);\n return;\n }\n try {\n const [liquidityGross, liquidityNet] = decodeFunctionResult({ abi: v4StateViewAbi, functionName: 'getTickLiquidity', data: result.returnData });\n ticks.push({ tick: chunk[i], liquidityGross, liquidityNet });\n } catch { failedTicks.push(chunk[i]); }\n });\n }\n return { ticks, failedWords, failedTicks, partial: unique.length < hi - lo + 1 || failedWords.length > 0 || failedTicks.length > 0 };\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import { type Address, type Hex, type PublicClient } from 'viem';
2
+ import type { UniswapV3ContractName, UniswapV3Deployment } from './deployments.js';
3
+ export interface UniswapV3CompatibilityReport {
4
+ chainId: number;
5
+ abiRevision: string;
6
+ contractsWithCode: readonly Address[];
7
+ runtimeCodeHashes: Readonly<Record<UniswapV3ContractName, Hex>>;
8
+ positionManagerFactory: Address;
9
+ positionManagerWrappedNative: Address;
10
+ }
11
+ /**
12
+ * Checks chain identity, exact runtime code hashes, and position-manager wiring.
13
+ */
14
+ export declare function verifyUniswapV3Compatibility(client: PublicClient, deployment: UniswapV3Deployment): Promise<UniswapV3CompatibilityReport>;
15
+ //# sourceMappingURL=compatibility.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compatibility.d.ts","sourceRoot":"","sources":["../src/compatibility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,YAAY,EAAE,MAAM,MAAM,CAAC;AAExF,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAGnF,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC,CAAC;IAChE,sBAAsB,EAAE,OAAO,CAAC;IAChC,4BAA4B,EAAE,OAAO,CAAC;CACvC;AAED;;GAEG;AACH,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,mBAAmB,GAC9B,OAAO,CAAC,4BAA4B,CAAC,CAoCvC"}
@@ -0,0 +1,57 @@
1
+ import { getAddress, keccak256 } from 'viem';
2
+ import { V3_ABI_REVISION, v3PositionManagerAbi } from './v3-abis.js';
3
+ import { rpc, UniswapSdkError } from './errors.js';
4
+ /**
5
+ * Checks chain identity, exact runtime code hashes, and position-manager wiring.
6
+ */
7
+ export async function verifyUniswapV3Compatibility(client, deployment) {
8
+ return rpc(async () => {
9
+ if (deployment.abiRevision !== V3_ABI_REVISION)
10
+ mismatch('deployment.abiRevision', V3_ABI_REVISION, deployment.abiRevision);
11
+ const chainId = await client.getChainId();
12
+ if (chainId !== deployment.chainId)
13
+ mismatch('chainId', deployment.chainId, chainId);
14
+ const contractNames = Object.keys(deployment.contracts);
15
+ const checked = contractNames.map(name => deployment.contracts[name]);
16
+ const runtimeCodeHashes = {};
17
+ for (const name of contractNames) {
18
+ const address = deployment.contracts[name];
19
+ const bytecode = await client.getBytecode({ address });
20
+ if (!bytecode || bytecode === '0x')
21
+ mismatch(`contracts.${address}`, 'deployed bytecode', bytecode ?? 'undefined');
22
+ const runtimeCodeHash = keccak256(bytecode);
23
+ if (runtimeCodeHash !== deployment.runtimeCodeHashes[name]) {
24
+ mismatch(`runtimeCodeHashes.${name}`, deployment.runtimeCodeHashes[name], runtimeCodeHash);
25
+ }
26
+ runtimeCodeHashes[name] = runtimeCodeHash;
27
+ }
28
+ const [factory, wrappedNative] = await Promise.all([
29
+ readAddress(client, deployment.contracts.nonfungiblePositionManager, 'factory'),
30
+ readAddress(client, deployment.contracts.nonfungiblePositionManager, 'WETH9'),
31
+ ]);
32
+ if (factory.toLowerCase() !== deployment.contracts.factory.toLowerCase())
33
+ mismatch('positionManager.factory', deployment.contracts.factory, factory);
34
+ if (wrappedNative.toLowerCase() !== deployment.contracts.wrappedNative.toLowerCase())
35
+ mismatch('positionManager.WETH9', deployment.contracts.wrappedNative, wrappedNative);
36
+ return {
37
+ chainId,
38
+ abiRevision: deployment.abiRevision,
39
+ contractsWithCode: checked,
40
+ runtimeCodeHashes,
41
+ positionManagerFactory: factory,
42
+ positionManagerWrappedNative: wrappedNative,
43
+ };
44
+ });
45
+ }
46
+ async function readAddress(client, address, functionName) {
47
+ const value = await client.readContract({ address, abi: v3PositionManagerAbi, functionName });
48
+ return getAddress(value);
49
+ }
50
+ function mismatch(path, expected, actual) {
51
+ throw new UniswapSdkError('DEPLOYMENT_MISMATCH', `${path} mismatch: expected ${String(expected)}, got ${String(actual)}`, {
52
+ path,
53
+ expected: String(expected),
54
+ actual: String(actual),
55
+ });
56
+ }
57
+ //# sourceMappingURL=compatibility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compatibility.js","sourceRoot":"","sources":["../src/compatibility.ts"],"names":[],"mappings":"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","sourcesContent":["import { getAddress, keccak256, type Address, type Hex, type PublicClient } from 'viem';\nimport { V3_ABI_REVISION, v3PositionManagerAbi } from './v3-abis.js';\nimport type { UniswapV3ContractName, UniswapV3Deployment } from './deployments.js';\nimport { rpc, UniswapSdkError } from './errors.js';\n\nexport interface UniswapV3CompatibilityReport {\n chainId: number;\n abiRevision: string;\n contractsWithCode: readonly Address[];\n runtimeCodeHashes: Readonly<Record<UniswapV3ContractName, Hex>>;\n positionManagerFactory: Address;\n positionManagerWrappedNative: Address;\n}\n\n/**\n * Checks chain identity, exact runtime code hashes, and position-manager wiring.\n */\nexport async function verifyUniswapV3Compatibility(\n client: PublicClient,\n deployment: UniswapV3Deployment,\n): Promise<UniswapV3CompatibilityReport> {\n return rpc(async () => {\n if (deployment.abiRevision !== V3_ABI_REVISION) mismatch('deployment.abiRevision', V3_ABI_REVISION, deployment.abiRevision);\n const chainId = await client.getChainId();\n if (chainId !== deployment.chainId) mismatch('chainId', deployment.chainId, chainId);\n\n const contractNames = Object.keys(deployment.contracts) as UniswapV3ContractName[];\n const checked = contractNames.map(name => deployment.contracts[name]);\n const runtimeCodeHashes = {} as Record<UniswapV3ContractName, Hex>;\n for (const name of contractNames) {\n const address = deployment.contracts[name];\n const bytecode = await client.getBytecode({ address });\n if (!bytecode || bytecode === '0x') mismatch(`contracts.${address}`, 'deployed bytecode', bytecode ?? 'undefined');\n const runtimeCodeHash = keccak256(bytecode);\n if (runtimeCodeHash !== deployment.runtimeCodeHashes[name]) {\n mismatch(`runtimeCodeHashes.${name}`, deployment.runtimeCodeHashes[name], runtimeCodeHash);\n }\n runtimeCodeHashes[name] = runtimeCodeHash;\n }\n\n const [factory, wrappedNative] = await Promise.all([\n readAddress(client, deployment.contracts.nonfungiblePositionManager, 'factory'),\n readAddress(client, deployment.contracts.nonfungiblePositionManager, 'WETH9'),\n ]);\n if (factory.toLowerCase() !== deployment.contracts.factory.toLowerCase()) mismatch('positionManager.factory', deployment.contracts.factory, factory);\n if (wrappedNative.toLowerCase() !== deployment.contracts.wrappedNative.toLowerCase()) mismatch('positionManager.WETH9', deployment.contracts.wrappedNative, wrappedNative);\n\n return {\n chainId,\n abiRevision: deployment.abiRevision,\n contractsWithCode: checked,\n runtimeCodeHashes,\n positionManagerFactory: factory,\n positionManagerWrappedNative: wrappedNative,\n };\n });\n}\n\nasync function readAddress(client: PublicClient, address: Address, functionName: 'factory' | 'WETH9'): Promise<Address> {\n const value = await client.readContract({ address, abi: v3PositionManagerAbi, functionName });\n return getAddress(value);\n}\n\nfunction mismatch(path: string, expected: unknown, actual: unknown): never {\n throw new UniswapSdkError('DEPLOYMENT_MISMATCH', `${path} mismatch: expected ${String(expected)}, got ${String(actual)}`, {\n path,\n expected: String(expected),\n actual: String(actual),\n });\n}\n"]}
@@ -0,0 +1,27 @@
1
+ import { type Address, type Hex } from 'viem';
2
+ export type RobinhoodUniswapV3DeploymentId = 'robinhood-mainnet-v3' | 'robinhood-testnet-v3';
3
+ export interface UniswapV3Contracts {
4
+ factory: Address;
5
+ nonfungiblePositionManager: Address;
6
+ quoterV2: Address;
7
+ swapRouter02: Address;
8
+ wrappedNative: Address;
9
+ multicall3: Address;
10
+ }
11
+ export type UniswapV3ContractName = keyof UniswapV3Contracts;
12
+ export type UniswapV3RuntimeCodeHashes = Readonly<Record<UniswapV3ContractName, Hex>>;
13
+ export interface UniswapV3Deployment {
14
+ id: RobinhoodUniswapV3DeploymentId;
15
+ chainId: number;
16
+ network: 'robinhood-chain-mainnet' | 'robinhood-chain-testnet';
17
+ abiRevision: string;
18
+ provenance: 'official' | 'reviewed-testnet';
19
+ explorerVerification: 'official' | 'partial';
20
+ reviewedAt: string;
21
+ contracts: UniswapV3Contracts;
22
+ runtimeCodeHashes: UniswapV3RuntimeCodeHashes;
23
+ }
24
+ export declare const robinhoodUniswapV3Mainnet: UniswapV3Deployment;
25
+ export declare const robinhoodUniswapV3Testnet: UniswapV3Deployment;
26
+ export declare function getRobinhoodUniswapV3Deployment(chainId: number): UniswapV3Deployment;
27
+ //# sourceMappingURL=deployments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployments.d.ts","sourceRoot":"","sources":["../src/deployments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAI1D,MAAM,MAAM,8BAA8B,GAAG,sBAAsB,GAAG,sBAAsB,CAAC;AAE7F,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,0BAA0B,EAAE,OAAO,CAAC;IACpC,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,kBAAkB,CAAC;AAC7D,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC,MAAM,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC,CAAC;AAEtF,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,8BAA8B,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,yBAAyB,GAAG,yBAAyB,CAAC;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,UAAU,GAAG,kBAAkB,CAAC;IAC5C,oBAAoB,EAAE,UAAU,GAAG,SAAS,CAAC;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,iBAAiB,EAAE,0BAA0B,CAAC;CAC/C;AAID,eAAO,MAAM,yBAAyB,EAAE,mBAwBtC,CAAC;AAEH,eAAO,MAAM,yBAAyB,EAAE,mBAwBtC,CAAC;AAEH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAIpF"}
@@ -0,0 +1,70 @@
1
+ import { getAddress } from 'viem';
2
+ import { V3_ABI_REVISION } from './v3-abis.js';
3
+ import { UniswapSdkError } from './errors.js';
4
+ const multicall3 = getAddress('0xca11bde05977b3631167028862be2a173976ca11');
5
+ export const robinhoodUniswapV3Mainnet = deepFreeze({
6
+ id: 'robinhood-mainnet-v3',
7
+ chainId: 4_663,
8
+ network: 'robinhood-chain-mainnet',
9
+ abiRevision: V3_ABI_REVISION,
10
+ provenance: 'official',
11
+ explorerVerification: 'official',
12
+ reviewedAt: '2026-09-11',
13
+ contracts: {
14
+ factory: getAddress('0x1f7d7550B1b028f7571E69A784071F0205FD2EfA'),
15
+ nonfungiblePositionManager: getAddress('0x73991a25C818Bf1f1128dEAaB1492D45638DE0D3'),
16
+ quoterV2: getAddress('0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7'),
17
+ swapRouter02: getAddress('0xcaf681a66d020601342297493863e78c959e5cb2'),
18
+ wrappedNative: getAddress('0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73'),
19
+ multicall3,
20
+ },
21
+ runtimeCodeHashes: {
22
+ factory: '0xec72b1abd1f2faee020cfea9c646bd8994f9fb389054f6e574f103a895091739',
23
+ nonfungiblePositionManager: '0x0a493d1af3d0f25fed8efa205244ebee14114267a08647fc38c515c7cd6ead4f',
24
+ quoterV2: '0x3db0868d945e9304c9bc6a8b2181948109ea617647142f3c4083e14393496a28',
25
+ swapRouter02: '0x6f36c378e272c6324c48f045182bcb54bd8ad654cf9ebd42e8893d52c4cb25dc',
26
+ wrappedNative: '0x5706be52f64875fee65a2cec0d80e47a23d8793cbe85d214b48445e2d05f5353',
27
+ multicall3: '0xd5c15df687b16f2ff992fc8d767b4216323184a2bbc6ee2f9c398c318e770891',
28
+ },
29
+ });
30
+ export const robinhoodUniswapV3Testnet = deepFreeze({
31
+ id: 'robinhood-testnet-v3',
32
+ chainId: 46_630,
33
+ network: 'robinhood-chain-testnet',
34
+ abiRevision: V3_ABI_REVISION,
35
+ provenance: 'reviewed-testnet',
36
+ explorerVerification: 'partial',
37
+ reviewedAt: '2026-09-11',
38
+ contracts: {
39
+ factory: getAddress('0xdf9e3D6ffaC4513dD7b053212bbECcbCD15ec932'),
40
+ nonfungiblePositionManager: getAddress('0xFFe6CFc4f759b65f9B62c9D05A9E21a78cE93e12'),
41
+ quoterV2: getAddress('0xDDcBe4989C8171F721c5e683C9C6339B59718213'),
42
+ swapRouter02: getAddress('0xb79cB26e90EBBD9bC02c75267c9a86dBa1AFedB7'),
43
+ wrappedNative: getAddress('0x7943e237c7F95DA44E0301572D358911207852Fa'),
44
+ multicall3,
45
+ },
46
+ runtimeCodeHashes: {
47
+ factory: '0x75c5bbc7989daa85188d9e4c9f989271d8bcb2abad3d47e6e47d3c0c5bff02c2',
48
+ nonfungiblePositionManager: '0xe40cd590528ac8b67b428579035fe391e502c38271623777692c50834688e9d5',
49
+ quoterV2: '0x724c4956e1c61fd13285a92685337df60254bc67f775e7268da2fc5cc79d5343',
50
+ swapRouter02: '0xdce781dc17d5f98e3ea0b72d88639a5995ccbba6e11bc01f2057a9409dc8c724',
51
+ wrappedNative: '0x5706be52f64875fee65a2cec0d80e47a23d8793cbe85d214b48445e2d05f5353',
52
+ multicall3: '0xd5c15df687b16f2ff992fc8d767b4216323184a2bbc6ee2f9c398c318e770891',
53
+ },
54
+ });
55
+ export function getRobinhoodUniswapV3Deployment(chainId) {
56
+ if (chainId === robinhoodUniswapV3Mainnet.chainId)
57
+ return robinhoodUniswapV3Mainnet;
58
+ if (chainId === robinhoodUniswapV3Testnet.chainId)
59
+ return robinhoodUniswapV3Testnet;
60
+ throw new UniswapSdkError('CHAIN_MISMATCH', `Unsupported Robinhood Uniswap v3 chain ID ${chainId}`);
61
+ }
62
+ function deepFreeze(value) {
63
+ if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) {
64
+ for (const child of Object.values(value))
65
+ deepFreeze(child);
66
+ Object.freeze(value);
67
+ }
68
+ return value;
69
+ }
70
+ //# sourceMappingURL=deployments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployments.js","sourceRoot":"","sources":["../src/deployments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA0B,MAAM,MAAM,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA4B9C,MAAM,UAAU,GAAG,UAAU,CAAC,4CAA4C,CAAC,CAAC;AAE5E,MAAM,CAAC,MAAM,yBAAyB,GAAwB,UAAU,CAAC;IACvE,EAAE,EAAE,sBAAsB;IAC1B,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,yBAAyB;IAClC,WAAW,EAAE,eAAe;IAC5B,UAAU,EAAE,UAAU;IACtB,oBAAoB,EAAE,UAAU;IAChC,UAAU,EAAE,YAAY;IACxB,SAAS,EAAE;QACT,OAAO,EAAE,UAAU,CAAC,4CAA4C,CAAC;QACjE,0BAA0B,EAAE,UAAU,CAAC,4CAA4C,CAAC;QACpF,QAAQ,EAAE,UAAU,CAAC,4CAA4C,CAAC;QAClE,YAAY,EAAE,UAAU,CAAC,4CAA4C,CAAC;QACtE,aAAa,EAAE,UAAU,CAAC,4CAA4C,CAAC;QACvE,UAAU;KACX;IACD,iBAAiB,EAAE;QACjB,OAAO,EAAE,oEAAoE;QAC7E,0BAA0B,EAAE,oEAAoE;QAChG,QAAQ,EAAE,oEAAoE;QAC9E,YAAY,EAAE,oEAAoE;QAClF,aAAa,EAAE,oEAAoE;QACnF,UAAU,EAAE,oEAAoE;KACjF;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,yBAAyB,GAAwB,UAAU,CAAC;IACvE,EAAE,EAAE,sBAAsB;IAC1B,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,yBAAyB;IAClC,WAAW,EAAE,eAAe;IAC5B,UAAU,EAAE,kBAAkB;IAC9B,oBAAoB,EAAE,SAAS;IAC/B,UAAU,EAAE,YAAY;IACxB,SAAS,EAAE;QACT,OAAO,EAAE,UAAU,CAAC,4CAA4C,CAAC;QACjE,0BAA0B,EAAE,UAAU,CAAC,4CAA4C,CAAC;QACpF,QAAQ,EAAE,UAAU,CAAC,4CAA4C,CAAC;QAClE,YAAY,EAAE,UAAU,CAAC,4CAA4C,CAAC;QACtE,aAAa,EAAE,UAAU,CAAC,4CAA4C,CAAC;QACvE,UAAU;KACX;IACD,iBAAiB,EAAE;QACjB,OAAO,EAAE,oEAAoE;QAC7E,0BAA0B,EAAE,oEAAoE;QAChG,QAAQ,EAAE,oEAAoE;QAC9E,YAAY,EAAE,oEAAoE;QAClF,aAAa,EAAE,oEAAoE;QACnF,UAAU,EAAE,oEAAoE;KACjF;CACF,CAAC,CAAC;AAEH,MAAM,UAAU,+BAA+B,CAAC,OAAe;IAC7D,IAAI,OAAO,KAAK,yBAAyB,CAAC,OAAO;QAAE,OAAO,yBAAyB,CAAC;IACpF,IAAI,OAAO,KAAK,yBAAyB,CAAC,OAAO;QAAE,OAAO,yBAAyB,CAAC;IACpF,MAAM,IAAI,eAAe,CAAC,gBAAgB,EAAE,6CAA6C,OAAO,EAAE,CAAC,CAAC;AACtG,CAAC;AAED,SAAS,UAAU,CAAI,KAAQ;IAC7B,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3E,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,KAAgC,CAAC;YAAE,UAAU,CAAC,KAAK,CAAC,CAAC;QACvF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { getAddress, type Address, type Hex } from 'viem';\nimport { V3_ABI_REVISION } from './v3-abis.js';\nimport { UniswapSdkError } from './errors.js';\n\nexport type RobinhoodUniswapV3DeploymentId = 'robinhood-mainnet-v3' | 'robinhood-testnet-v3';\n\nexport interface UniswapV3Contracts {\n factory: Address;\n nonfungiblePositionManager: Address;\n quoterV2: Address;\n swapRouter02: Address;\n wrappedNative: Address;\n multicall3: Address;\n}\n\nexport type UniswapV3ContractName = keyof UniswapV3Contracts;\nexport type UniswapV3RuntimeCodeHashes = Readonly<Record<UniswapV3ContractName, Hex>>;\n\nexport interface UniswapV3Deployment {\n id: RobinhoodUniswapV3DeploymentId;\n chainId: number;\n network: 'robinhood-chain-mainnet' | 'robinhood-chain-testnet';\n abiRevision: string;\n provenance: 'official' | 'reviewed-testnet';\n explorerVerification: 'official' | 'partial';\n reviewedAt: string;\n contracts: UniswapV3Contracts;\n runtimeCodeHashes: UniswapV3RuntimeCodeHashes;\n}\n\nconst multicall3 = getAddress('0xca11bde05977b3631167028862be2a173976ca11');\n\nexport const robinhoodUniswapV3Mainnet: UniswapV3Deployment = deepFreeze({\n id: 'robinhood-mainnet-v3',\n chainId: 4_663,\n network: 'robinhood-chain-mainnet',\n abiRevision: V3_ABI_REVISION,\n provenance: 'official',\n explorerVerification: 'official',\n reviewedAt: '2026-09-11',\n contracts: {\n factory: getAddress('0x1f7d7550B1b028f7571E69A784071F0205FD2EfA'),\n nonfungiblePositionManager: getAddress('0x73991a25C818Bf1f1128dEAaB1492D45638DE0D3'),\n quoterV2: getAddress('0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7'),\n swapRouter02: getAddress('0xcaf681a66d020601342297493863e78c959e5cb2'),\n wrappedNative: getAddress('0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73'),\n multicall3,\n },\n runtimeCodeHashes: {\n factory: '0xec72b1abd1f2faee020cfea9c646bd8994f9fb389054f6e574f103a895091739',\n nonfungiblePositionManager: '0x0a493d1af3d0f25fed8efa205244ebee14114267a08647fc38c515c7cd6ead4f',\n quoterV2: '0x3db0868d945e9304c9bc6a8b2181948109ea617647142f3c4083e14393496a28',\n swapRouter02: '0x6f36c378e272c6324c48f045182bcb54bd8ad654cf9ebd42e8893d52c4cb25dc',\n wrappedNative: '0x5706be52f64875fee65a2cec0d80e47a23d8793cbe85d214b48445e2d05f5353',\n multicall3: '0xd5c15df687b16f2ff992fc8d767b4216323184a2bbc6ee2f9c398c318e770891',\n },\n});\n\nexport const robinhoodUniswapV3Testnet: UniswapV3Deployment = deepFreeze({\n id: 'robinhood-testnet-v3',\n chainId: 46_630,\n network: 'robinhood-chain-testnet',\n abiRevision: V3_ABI_REVISION,\n provenance: 'reviewed-testnet',\n explorerVerification: 'partial',\n reviewedAt: '2026-09-11',\n contracts: {\n factory: getAddress('0xdf9e3D6ffaC4513dD7b053212bbECcbCD15ec932'),\n nonfungiblePositionManager: getAddress('0xFFe6CFc4f759b65f9B62c9D05A9E21a78cE93e12'),\n quoterV2: getAddress('0xDDcBe4989C8171F721c5e683C9C6339B59718213'),\n swapRouter02: getAddress('0xb79cB26e90EBBD9bC02c75267c9a86dBa1AFedB7'),\n wrappedNative: getAddress('0x7943e237c7F95DA44E0301572D358911207852Fa'),\n multicall3,\n },\n runtimeCodeHashes: {\n factory: '0x75c5bbc7989daa85188d9e4c9f989271d8bcb2abad3d47e6e47d3c0c5bff02c2',\n nonfungiblePositionManager: '0xe40cd590528ac8b67b428579035fe391e502c38271623777692c50834688e9d5',\n quoterV2: '0x724c4956e1c61fd13285a92685337df60254bc67f775e7268da2fc5cc79d5343',\n swapRouter02: '0xdce781dc17d5f98e3ea0b72d88639a5995ccbba6e11bc01f2057a9409dc8c724',\n wrappedNative: '0x5706be52f64875fee65a2cec0d80e47a23d8793cbe85d214b48445e2d05f5353',\n multicall3: '0xd5c15df687b16f2ff992fc8d767b4216323184a2bbc6ee2f9c398c318e770891',\n },\n});\n\nexport function getRobinhoodUniswapV3Deployment(chainId: number): UniswapV3Deployment {\n if (chainId === robinhoodUniswapV3Mainnet.chainId) return robinhoodUniswapV3Mainnet;\n if (chainId === robinhoodUniswapV3Testnet.chainId) return robinhoodUniswapV3Testnet;\n throw new UniswapSdkError('CHAIN_MISMATCH', `Unsupported Robinhood Uniswap v3 chain ID ${chainId}`);\n}\n\nfunction deepFreeze<T>(value: T): T {\n if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) {\n for (const child of Object.values(value as Record<string, unknown>)) deepFreeze(child);\n Object.freeze(value);\n }\n return value;\n}\n"]}
@@ -0,0 +1,24 @@
1
+ import { type V4Deployment, type V4PoolKey } from './pool.js';
2
+ import { type V4Observation, type V4ReadClient } from './reads.js';
3
+ export interface V4Tick {
4
+ tick: number;
5
+ liquidityGross: bigint;
6
+ liquidityNet: bigint;
7
+ }
8
+ export interface V4TickWindow extends V4Observation {
9
+ ticks: V4Tick[];
10
+ fromWord: number;
11
+ toWord: number;
12
+ /** True for an incomplete range OR any failed bitmap/tick observation. */
13
+ partial: boolean;
14
+ failedWords: number[];
15
+ failedTicks: number[];
16
+ }
17
+ export declare function ticksInWord(wordPosition: number, bitmap: bigint, tickSpacing: number): number[];
18
+ /** Raw initialized ticks, not an assertion of complete executable hook-adjusted depth. */
19
+ export declare function readV4TickWindow(client: V4ReadClient, deployment: V4Deployment, key: V4PoolKey, options: {
20
+ fromWord: number;
21
+ toWord: number;
22
+ blockNumber?: bigint;
23
+ }): Promise<V4TickWindow>;
24
+ //# sourceMappingURL=depth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"depth.d.ts","sourceRoot":"","sources":["../src/depth.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC7E,OAAO,EAAmC,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAEpG,MAAM,WAAW,MAAM;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE;AACtF,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAY/F;AAED,0FAA0F;AAC1F,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAoCjM"}
package/dist/depth.js ADDED
@@ -0,0 +1,65 @@
1
+ import { v4StateViewAbi } from './abis.js';
2
+ import { invalid, rpc } from './errors.js';
3
+ import { poolReference } from './pool.js';
4
+ import { assertManager, observationBlock } from './reads.js';
5
+ export function ticksInWord(wordPosition, bitmap, tickSpacing) {
6
+ if (!Number.isInteger(wordPosition) || wordPosition < -32768 || wordPosition > 32767)
7
+ invalid('wordPosition must be int16');
8
+ if (typeof bitmap !== 'bigint' || bitmap < 0n || bitmap >= 1n << 256n)
9
+ invalid('bitmap must be uint256');
10
+ if (!Number.isInteger(tickSpacing) || tickSpacing < 1 || tickSpacing > 32767)
11
+ invalid('tickSpacing must be between 1 and 32767');
12
+ const ticks = [];
13
+ for (let bit = 0; bit < 256; bit++) {
14
+ if ((bitmap & (1n << BigInt(bit))) !== 0n) {
15
+ const tick = (wordPosition * 256 + bit) * tickSpacing;
16
+ if (tick >= -887272 && tick <= 887272)
17
+ ticks.push(tick);
18
+ }
19
+ }
20
+ return ticks;
21
+ }
22
+ /** Raw initialized ticks, not an assertion of complete executable hook-adjusted depth. */
23
+ export async function readV4TickWindow(client, deployment, key, options) {
24
+ const reference = poolReference(deployment, key);
25
+ const minTick = Math.ceil(-887272 / key.tickSpacing) * key.tickSpacing;
26
+ const maxTick = Math.floor(887272 / key.tickSpacing) * key.tickSpacing;
27
+ const minWord = Math.floor(minTick / key.tickSpacing / 256);
28
+ const maxWord = Math.floor(maxTick / key.tickSpacing / 256);
29
+ const { fromWord, toWord } = options;
30
+ if (!Number.isInteger(fromWord) || !Number.isInteger(toWord) || fromWord < minWord || toWord > maxWord || fromWord > toWord || toWord - fromWord >= 16)
31
+ invalid('Choose an ordered window of at most 16 bitmap words within the usable tick range');
32
+ const blockNumber = await observationBlock(client, deployment, options.blockNumber);
33
+ await assertManager(client, deployment, deployment.stateView, blockNumber);
34
+ const failedWords = [];
35
+ const failedTicks = [];
36
+ const ticks = [];
37
+ const words = Array.from({ length: toWord - fromWord + 1 }, (_, i) => fromWord + i);
38
+ const wordResults = await Promise.allSettled(words.map(word => client.readContract({
39
+ address: deployment.stateView, abi: v4StateViewAbi, functionName: 'getTickBitmap', args: [reference.poolId, word], blockNumber,
40
+ })));
41
+ const coordinates = [];
42
+ wordResults.forEach((result, i) => {
43
+ if (result.status === 'rejected')
44
+ failedWords.push(words[i]);
45
+ else
46
+ coordinates.push(...ticksInWord(words[i], result.value, key.tickSpacing));
47
+ });
48
+ for (let offset = 0; offset < coordinates.length; offset += 16) {
49
+ const batch = coordinates.slice(offset, offset + 16);
50
+ const results = await Promise.allSettled(batch.map(tick => client.readContract({
51
+ address: deployment.stateView, abi: v4StateViewAbi, functionName: 'getTickLiquidity', args: [reference.poolId, tick], blockNumber,
52
+ })));
53
+ results.forEach((result, i) => {
54
+ if (result.status === 'rejected')
55
+ failedTicks.push(batch[i]);
56
+ else
57
+ ticks.push({ tick: batch[i], liquidityGross: result.value[0], liquidityNet: result.value[1] });
58
+ });
59
+ }
60
+ // A transport failure during the scan cannot silently relabel another chain's observations.
61
+ await rpc(() => observationBlock(client, deployment, blockNumber));
62
+ return { ...reference, blockNumber, fromWord, toWord, ticks, failedWords, failedTicks,
63
+ partial: fromWord !== minWord || toWord !== maxWord || failedWords.length > 0 || failedTicks.length > 0 };
64
+ }
65
+ //# sourceMappingURL=depth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"depth.js","sourceRoot":"","sources":["../src/depth.ts"],"names":[],"mappings":"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","sourcesContent":["import { v4StateViewAbi } from './abis.js';\nimport { invalid, rpc } from './errors.js';\nimport { poolReference, type V4Deployment, type V4PoolKey } from './pool.js';\nimport { assertManager, observationBlock, type V4Observation, type V4ReadClient } from './reads.js';\n\nexport interface V4Tick { tick: number; liquidityGross: bigint; liquidityNet: bigint }\nexport interface V4TickWindow extends V4Observation {\n ticks: V4Tick[];\n fromWord: number;\n toWord: number;\n /** True for an incomplete range OR any failed bitmap/tick observation. */\n partial: boolean;\n failedWords: number[];\n failedTicks: number[];\n}\n\nexport function ticksInWord(wordPosition: number, bitmap: bigint, tickSpacing: number): number[] {\n if (!Number.isInteger(wordPosition) || wordPosition < -32768 || wordPosition > 32767) invalid('wordPosition must be int16');\n if (typeof bitmap !== 'bigint' || bitmap < 0n || bitmap >= 1n << 256n) invalid('bitmap must be uint256');\n if (!Number.isInteger(tickSpacing) || tickSpacing < 1 || tickSpacing > 32767) invalid('tickSpacing must be between 1 and 32767');\n const ticks: number[] = [];\n for (let bit = 0; bit < 256; bit++) {\n if ((bitmap & (1n << BigInt(bit))) !== 0n) {\n const tick = (wordPosition * 256 + bit) * tickSpacing;\n if (tick >= -887272 && tick <= 887272) ticks.push(tick);\n }\n }\n return ticks;\n}\n\n/** Raw initialized ticks, not an assertion of complete executable hook-adjusted depth. */\nexport async function readV4TickWindow(client: V4ReadClient, deployment: V4Deployment, key: V4PoolKey, options: { fromWord: number; toWord: number; blockNumber?: bigint }): Promise<V4TickWindow> {\n const reference = poolReference(deployment, key);\n const minTick = Math.ceil(-887272 / key.tickSpacing) * key.tickSpacing;\n const maxTick = Math.floor(887272 / key.tickSpacing) * key.tickSpacing;\n const minWord = Math.floor(minTick / key.tickSpacing / 256);\n const maxWord = Math.floor(maxTick / key.tickSpacing / 256);\n const { fromWord, toWord } = options;\n if (!Number.isInteger(fromWord) || !Number.isInteger(toWord) || fromWord < minWord || toWord > maxWord || fromWord > toWord || toWord - fromWord >= 16) invalid('Choose an ordered window of at most 16 bitmap words within the usable tick range');\n const blockNumber = await observationBlock(client, deployment, options.blockNumber);\n await assertManager(client, deployment, deployment.stateView, blockNumber);\n const failedWords: number[] = [];\n const failedTicks: number[] = [];\n const ticks: V4Tick[] = [];\n const words = Array.from({ length: toWord - fromWord + 1 }, (_, i) => fromWord + i);\n const wordResults = await Promise.allSettled(words.map(word => client.readContract({\n address: deployment.stateView, abi: v4StateViewAbi, functionName: 'getTickBitmap', args: [reference.poolId, word], blockNumber,\n })));\n const coordinates: number[] = [];\n wordResults.forEach((result, i) => {\n if (result.status === 'rejected') failedWords.push(words[i]);\n else coordinates.push(...ticksInWord(words[i], result.value, key.tickSpacing));\n });\n for (let offset = 0; offset < coordinates.length; offset += 16) {\n const batch = coordinates.slice(offset, offset + 16);\n const results = await Promise.allSettled(batch.map(tick => client.readContract({\n address: deployment.stateView, abi: v4StateViewAbi, functionName: 'getTickLiquidity', args: [reference.poolId, tick], blockNumber,\n })));\n results.forEach((result, i) => {\n if (result.status === 'rejected') failedTicks.push(batch[i]);\n else ticks.push({ tick: batch[i], liquidityGross: result.value[0], liquidityNet: result.value[1] });\n });\n }\n // A transport failure during the scan cannot silently relabel another chain's observations.\n await rpc(() => observationBlock(client, deployment, blockNumber));\n return { ...reference, blockNumber, fromWord, toWord, ticks, failedWords, failedTicks,\n partial: fromWord !== minWord || toWord !== maxWord || failedWords.length > 0 || failedTicks.length > 0 };\n}\n"]}
@@ -0,0 +1,25 @@
1
+ export type UniswapErrorCode = 'INVALID_ARGUMENT' | 'CHAIN_MISMATCH' | 'DEPLOYMENT_MISMATCH' | 'POOL_NOT_FOUND' | 'RPC_ERROR' | 'QUOTE_FAILED' | 'CALLDATA_MISMATCH' | 'EVENT_NOT_FOUND';
2
+ export interface UniswapSdkErrorOptions extends ErrorOptions {
3
+ path?: string;
4
+ expected?: string;
5
+ actual?: string;
6
+ }
7
+ export declare class UniswapSdkError extends Error {
8
+ readonly code: UniswapErrorCode;
9
+ readonly path?: string;
10
+ readonly expected?: string;
11
+ readonly actual?: string;
12
+ constructor(code: UniswapErrorCode, message: string, options?: UniswapSdkErrorOptions);
13
+ toJSON(): {
14
+ name: string;
15
+ code: UniswapErrorCode;
16
+ message: string;
17
+ path: string | undefined;
18
+ expected: string | undefined;
19
+ actual: string | undefined;
20
+ };
21
+ }
22
+ export declare function isUniswapSdkError(value: unknown): value is UniswapSdkError;
23
+ export declare function invalid(message: string): never;
24
+ export declare function rpc<T>(operation: () => Promise<T>): Promise<T>;
25
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,qBAAqB,GAAG,gBAAgB,GAAG,WAAW,GAAG,cAAc,GAAG,mBAAmB,GAAG,iBAAiB,CAAC;AAEzL,MAAM,WAAW,sBAAuB,SAAQ,YAAY;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,eAAgB,SAAQ,KAAK;aAKZ,IAAI,EAAE,gBAAgB;IAJlD,SAAgB,IAAI,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAgB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClC,SAAgB,MAAM,CAAC,EAAE,MAAM,CAAC;gBAEJ,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B;IAOzG,MAAM;;;;;;;;CAGP;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAE1E;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAA4D;AAE3G,wBAAsB,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAMpE"}
package/dist/errors.js ADDED
@@ -0,0 +1,32 @@
1
+ export class UniswapSdkError extends Error {
2
+ code;
3
+ path;
4
+ expected;
5
+ actual;
6
+ constructor(code, message, options = {}) {
7
+ super(message, options);
8
+ this.code = code;
9
+ this.name = 'UniswapSdkError';
10
+ this.path = options.path;
11
+ this.expected = options.expected;
12
+ this.actual = options.actual;
13
+ }
14
+ toJSON() {
15
+ return { name: this.name, code: this.code, message: this.message, path: this.path, expected: this.expected, actual: this.actual };
16
+ }
17
+ }
18
+ export function isUniswapSdkError(value) {
19
+ return value instanceof UniswapSdkError;
20
+ }
21
+ export function invalid(message) { throw new UniswapSdkError('INVALID_ARGUMENT', message); }
22
+ export async function rpc(operation) {
23
+ try {
24
+ return await operation();
25
+ }
26
+ catch (cause) {
27
+ if (cause instanceof UniswapSdkError)
28
+ throw cause;
29
+ throw new UniswapSdkError('RPC_ERROR', 'Uniswap RPC observation failed', { cause });
30
+ }
31
+ }
32
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAQA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAKZ;IAJZ,IAAI,CAAU;IACd,QAAQ,CAAU;IAClB,MAAM,CAAU;IAEhC,YAA4B,IAAsB,EAAE,OAAe,EAAE,UAAkC,EAAE;QACvG,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QADE,SAAI,GAAJ,IAAI,CAAkB;QAEhD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC/B,CAAC;IACD,MAAM;QACJ,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IACpI,CAAC;CACF;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,OAAO,KAAK,YAAY,eAAe,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,OAAe,IAAW,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAE3G,MAAM,CAAC,KAAK,UAAU,GAAG,CAAI,SAA2B;IACtD,IAAI,CAAC;QAAC,OAAO,MAAM,SAAS,EAAE,CAAC;IAAC,CAAC;IACjC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,KAAK,YAAY,eAAe;YAAE,MAAM,KAAK,CAAC;QAClD,MAAM,IAAI,eAAe,CAAC,WAAW,EAAE,gCAAgC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACtF,CAAC;AACH,CAAC","sourcesContent":["export type UniswapErrorCode = 'INVALID_ARGUMENT' | 'CHAIN_MISMATCH' | 'DEPLOYMENT_MISMATCH' | 'POOL_NOT_FOUND' | 'RPC_ERROR' | 'QUOTE_FAILED' | 'CALLDATA_MISMATCH' | 'EVENT_NOT_FOUND';\n\nexport interface UniswapSdkErrorOptions extends ErrorOptions {\n path?: string;\n expected?: string;\n actual?: string;\n}\n\nexport class UniswapSdkError extends Error {\n public readonly path?: string;\n public readonly expected?: string;\n public readonly actual?: string;\n\n constructor(public readonly code: UniswapErrorCode, message: string, options: UniswapSdkErrorOptions = {}) {\n super(message, options);\n this.name = 'UniswapSdkError';\n this.path = options.path;\n this.expected = options.expected;\n this.actual = options.actual;\n }\n toJSON() {\n return { name: this.name, code: this.code, message: this.message, path: this.path, expected: this.expected, actual: this.actual };\n }\n}\n\nexport function isUniswapSdkError(value: unknown): value is UniswapSdkError {\n return value instanceof UniswapSdkError;\n}\n\nexport function invalid(message: string): never { throw new UniswapSdkError('INVALID_ARGUMENT', message); }\n\nexport async function rpc<T>(operation: () => Promise<T>): Promise<T> {\n try { return await operation(); }\n catch (cause) {\n if (cause instanceof UniswapSdkError) throw cause;\n throw new UniswapSdkError('RPC_ERROR', 'Uniswap RPC observation failed', { cause });\n }\n}\n"]}
@@ -0,0 +1,23 @@
1
+ import { type Address, type Hex } from 'viem';
2
+ import { type V4Deployment } from './pool.js';
3
+ /** Normalize an Initialize log supplied by an indexer or bounded RPC scan. */
4
+ export declare function decodeV4PoolInitialization(deployment: V4Deployment, log: {
5
+ address: Address;
6
+ data: Hex;
7
+ topics: [Hex, ...Hex[]];
8
+ blockNumber: bigint;
9
+ transactionHash: Hex;
10
+ logIndex: number;
11
+ removed?: boolean;
12
+ }): {
13
+ sqrtPriceX96: bigint;
14
+ tick: number;
15
+ blockNumber: bigint;
16
+ transactionHash: `0x${string}`;
17
+ logIndex: number;
18
+ chainId: number;
19
+ poolManager: Address;
20
+ poolId: Hex;
21
+ key: import("./pool.js").V4PoolKey;
22
+ };
23
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAG9D,OAAO,EAAiC,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAE7E,8EAA8E;AAC9E,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,YAAY,EAAE,GAAG,EAAE;IACxE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,GAAG,CAAC;IAAC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,GAAG,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CACtI;;;;;;;;;;EAeA"}