@reptilianhq/uniswap-sdk 0.2.2 → 0.3.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.
@@ -0,0 +1,44 @@
1
+ import type { Address } from 'viem';
2
+ /**
3
+ * A v4 hook's capability bits, decoded from its address. Field names match
4
+ * Uniswap's `Hooks.sol`. Declared independently of `@uniswap/v4-sdk`'s own
5
+ * `HookPermissions` (keyed by its nominal `HookOptions` enum) so callers can
6
+ * work with plain string keys instead of importing that enum too.
7
+ */
8
+ export interface V4HookPermissions {
9
+ beforeInitialize: boolean;
10
+ afterInitialize: boolean;
11
+ beforeAddLiquidity: boolean;
12
+ afterAddLiquidity: boolean;
13
+ beforeRemoveLiquidity: boolean;
14
+ afterRemoveLiquidity: boolean;
15
+ beforeSwap: boolean;
16
+ afterSwap: boolean;
17
+ beforeDonate: boolean;
18
+ afterDonate: boolean;
19
+ beforeSwapReturnsDelta: boolean;
20
+ afterSwapReturnsDelta: boolean;
21
+ afterAddLiquidityReturnsDelta: boolean;
22
+ afterRemoveLiquidityReturnsDelta: boolean;
23
+ }
24
+ /**
25
+ * A v4 hook address encodes which PoolManager callbacks it implements in its low 14 bits
26
+ * (mined via CREATE2, so PoolManager can check permissions without an external call).
27
+ * Delegates the bit-to-callback mapping to `@uniswap/v4-sdk`'s `Hook` class rather than
28
+ * re-deriving it, so the mapping stays pinned to a versioned upstream dependency instead
29
+ * of drifting from memory.
30
+ */
31
+ export declare function decodeV4HookPermissions(address: Address): V4HookPermissions;
32
+ /**
33
+ * The permission flags a hook implements that are not in `modelled`, i.e. the
34
+ * behaviour a caller has not accounted for. Empty means every flag the hook
35
+ * sets is one the caller already knows how to price and verify.
36
+ *
37
+ * This does not judge economic safety (tax rates, whether principal is
38
+ * locked) — only whether the hook's *shape* is fully understood. That
39
+ * judgement, and what "modelled" means for a given protocol, belongs to the
40
+ * caller: a beforeSwap hook is fine to a caller that prices beforeSwap price
41
+ * moves and unsafe to one that does not.
42
+ */
43
+ export declare function unmodelledV4HookPermissions(address: Address, modelled: Iterable<keyof V4HookPermissions>): (keyof V4HookPermissions)[];
44
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,sBAAsB,EAAE,OAAO,CAAC;IAChC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,6BAA6B,EAAE,OAAO,CAAC;IACvC,gCAAgC,EAAE,OAAO,CAAC;CAC3C;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,iBAAiB,CAE3E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,CAAC,MAAM,iBAAiB,CAAC,GAC1C,CAAC,MAAM,iBAAiB,CAAC,EAAE,CAM7B"}
package/dist/hooks.js ADDED
@@ -0,0 +1,29 @@
1
+ import { Hook } from './official-sdk.cjs';
2
+ import { checkedAddress } from './pool.js';
3
+ /**
4
+ * A v4 hook address encodes which PoolManager callbacks it implements in its low 14 bits
5
+ * (mined via CREATE2, so PoolManager can check permissions without an external call).
6
+ * Delegates the bit-to-callback mapping to `@uniswap/v4-sdk`'s `Hook` class rather than
7
+ * re-deriving it, so the mapping stays pinned to a versioned upstream dependency instead
8
+ * of drifting from memory.
9
+ */
10
+ export function decodeV4HookPermissions(address) {
11
+ return Hook.permissions(checkedAddress(address));
12
+ }
13
+ /**
14
+ * The permission flags a hook implements that are not in `modelled`, i.e. the
15
+ * behaviour a caller has not accounted for. Empty means every flag the hook
16
+ * sets is one the caller already knows how to price and verify.
17
+ *
18
+ * This does not judge economic safety (tax rates, whether principal is
19
+ * locked) — only whether the hook's *shape* is fully understood. That
20
+ * judgement, and what "modelled" means for a given protocol, belongs to the
21
+ * caller: a beforeSwap hook is fine to a caller that prices beforeSwap price
22
+ * moves and unsafe to one that does not.
23
+ */
24
+ export function unmodelledV4HookPermissions(address, modelled) {
25
+ const allowed = new Set(modelled);
26
+ const permissions = decodeV4HookPermissions(address);
27
+ return Object.keys(permissions).filter(flag => permissions[flag] && !allowed.has(flag));
28
+ }
29
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAyB3C;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAgB;IACtD,OAAO,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,OAAO,CAAC,CAAsB,CAAC;AACxE,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,2BAA2B,CACzC,OAAgB,EAChB,QAA2C;IAE3C,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClC,MAAM,WAAW,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACrD,OAAQ,MAAM,CAAC,IAAI,CAAC,WAAW,CAAiC,CAAC,MAAM,CACrE,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAChD,CAAC;AACJ,CAAC","sourcesContent":["import { Hook } from './official-sdk.cjs';\nimport type { Address } from 'viem';\nimport { checkedAddress } from './pool.js';\n\n/**\n * A v4 hook's capability bits, decoded from its address. Field names match\n * Uniswap's `Hooks.sol`. Declared independently of `@uniswap/v4-sdk`'s own\n * `HookPermissions` (keyed by its nominal `HookOptions` enum) so callers can\n * work with plain string keys instead of importing that enum too.\n */\nexport interface V4HookPermissions {\n beforeInitialize: boolean;\n afterInitialize: boolean;\n beforeAddLiquidity: boolean;\n afterAddLiquidity: boolean;\n beforeRemoveLiquidity: boolean;\n afterRemoveLiquidity: boolean;\n beforeSwap: boolean;\n afterSwap: boolean;\n beforeDonate: boolean;\n afterDonate: boolean;\n beforeSwapReturnsDelta: boolean;\n afterSwapReturnsDelta: boolean;\n afterAddLiquidityReturnsDelta: boolean;\n afterRemoveLiquidityReturnsDelta: boolean;\n}\n\n/**\n * A v4 hook address encodes which PoolManager callbacks it implements in its low 14 bits\n * (mined via CREATE2, so PoolManager can check permissions without an external call).\n * Delegates the bit-to-callback mapping to `@uniswap/v4-sdk`'s `Hook` class rather than\n * re-deriving it, so the mapping stays pinned to a versioned upstream dependency instead\n * of drifting from memory.\n */\nexport function decodeV4HookPermissions(address: Address): V4HookPermissions {\n return Hook.permissions(checkedAddress(address)) as V4HookPermissions;\n}\n\n/**\n * The permission flags a hook implements that are not in `modelled`, i.e. the\n * behaviour a caller has not accounted for. Empty means every flag the hook\n * sets is one the caller already knows how to price and verify.\n *\n * This does not judge economic safety (tax rates, whether principal is\n * locked) — only whether the hook's *shape* is fully understood. That\n * judgement, and what \"modelled\" means for a given protocol, belongs to the\n * caller: a beforeSwap hook is fine to a caller that prices beforeSwap price\n * moves and unsafe to one that does not.\n */\nexport function unmodelledV4HookPermissions(\n address: Address,\n modelled: Iterable<keyof V4HookPermissions>,\n): (keyof V4HookPermissions)[] {\n const allowed = new Set(modelled);\n const permissions = decodeV4HookPermissions(address);\n return (Object.keys(permissions) as (keyof V4HookPermissions)[]).filter(\n flag => permissions[flag] && !allowed.has(flag),\n );\n}\n"]}
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Pool = void 0;
3
+ exports.Hook = exports.Pool = void 0;
4
4
  // Upstream 2.3.3's ESM export contains extensionless directory imports that
5
5
  // native Node cannot resolve. Its public require export works in Node and
6
6
  // bundlers. Keep this compatibility seam local instead of forking the SDK.
7
7
  var v4_sdk_1 = require("@uniswap/v4-sdk");
8
8
  Object.defineProperty(exports, "Pool", { enumerable: true, get: function () { return v4_sdk_1.Pool; } });
9
+ Object.defineProperty(exports, "Hook", { enumerable: true, get: function () { return v4_sdk_1.Hook; } });
9
10
  //# sourceMappingURL=official-sdk.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"official-sdk.cjs","sourceRoot":"","sources":["../src/official-sdk.cts"],"names":[],"mappings":";;;AAAA,4EAA4E;AAC5E,0EAA0E;AAC1E,2EAA2E;AAC3E,0CAAuC;AAA9B,8FAAA,IAAI,OAAA","sourcesContent":["// Upstream 2.3.3's ESM export contains extensionless directory imports that\n// native Node cannot resolve. Its public require export works in Node and\n// bundlers. Keep this compatibility seam local instead of forking the SDK.\nexport { Pool } from '@uniswap/v4-sdk';\n"]}
1
+ {"version":3,"file":"official-sdk.cjs","sourceRoot":"","sources":["../src/official-sdk.cts"],"names":[],"mappings":";;;AAAA,4EAA4E;AAC5E,0EAA0E;AAC1E,2EAA2E;AAC3E,0CAA6C;AAApC,8FAAA,IAAI,OAAA;AAAE,8FAAA,IAAI,OAAA","sourcesContent":["// Upstream 2.3.3's ESM export contains extensionless directory imports that\n// native Node cannot resolve. Its public require export works in Node and\n// bundlers. Keep this compatibility seam local instead of forking the SDK.\nexport { Pool, Hook } from '@uniswap/v4-sdk';\n"]}
@@ -1,2 +1,2 @@
1
- export { Pool } from '@uniswap/v4-sdk';
1
+ export { Pool, Hook } from '@uniswap/v4-sdk';
2
2
  //# sourceMappingURL=official-sdk.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"official-sdk.d.cts","sourceRoot":"","sources":["../src/official-sdk.cts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"official-sdk.d.cts","sourceRoot":"","sources":["../src/official-sdk.cts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { type Address, type Hex } from 'viem';
2
2
  import { type V4PoolReference } from './pool.js';
3
+ import { type V4HookPermissions } from './hooks.js';
3
4
  /** Structural contract implemented by protocol SDKs; contains no transport or signer. */
4
5
  export interface V4ProviderDescriptor {
5
6
  schemaVersion: 1;
@@ -10,6 +11,15 @@ export interface V4ProviderDescriptor {
10
11
  poolManager: Address;
11
12
  startBlock: bigint;
12
13
  hooks: readonly Address[];
14
+ /**
15
+ * Permission flags this provider has reviewed across `hooks` — what its hooks
16
+ * are known to do (tax a swap, gate initialization, etc.), not judged here.
17
+ * When present, every hook in `hooks` must implement only these flags, so a
18
+ * provider that has not reviewed a hook's full behaviour cannot silently pass
19
+ * verification once that hook starts using an extra callback. Optional so a
20
+ * provider can adopt this check independently of every other provider.
21
+ */
22
+ modelledHookPermissions?: readonly (keyof V4HookPermissions)[];
13
23
  discovery: {
14
24
  address: Address;
15
25
  eventSignature: string;
@@ -1 +1 @@
1
- {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+C,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAC3F,OAAO,EAA+B,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAG9E,yFAAyF;AACzF,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,CAAC,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,YAAY,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,OAAO,EAAE,CAAC;IAC1B,SAAS,EAAE;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;QACxB,uBAAuB,EAAE,GAAG,CAAC;KAC9B,CAAC;IACF,UAAU,EAAE,SAAS,WAAW,EAAE,CAAC;CACpC;AACD,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,MAAM,GAAG,iBAAiB,GAAG,QAAQ,CAAC;AAQ/E,6FAA6F;AAC7F,MAAM,WAAW,cAAe,SAAQ,eAAe;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE;QACV,aAAa,EAAE,OAAO,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,GAAG,CAAC;QACf,eAAe,EAAE,GAAG,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAQD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAW/E;AAED,gGAAgG;AAChG,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAY/F;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,oBAAoB,EAAE,KAAK,EAAE,SAAS,cAAc,EAAE,EAAE,OAAO,EAAE;IAClH,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAClE,SAAS,EAAE;QAAE,qBAAqB,EAAE,OAAO,CAAA;KAAE,CAAC;CAC/C;gBA2B4B,MAAM;kBAAgB,MAAM;aAAW,MAAM;aAAW,OAAO;eAAa,MAAM;aAAW,MAAM;YAAU,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,EAAE,CAAC;IAWvK"}
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+C,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAC3F,OAAO,EAA+B,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,EAA+B,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGjF,yFAAyF;AACzF,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,CAAC,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,YAAY,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,OAAO,EAAE,CAAC;IAC1B;;;;;;;OAOG;IACH,uBAAuB,CAAC,EAAE,SAAS,CAAC,MAAM,iBAAiB,CAAC,EAAE,CAAC;IAC/D,SAAS,EAAE;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;QACxB,uBAAuB,EAAE,GAAG,CAAC;KAC9B,CAAC;IACF,UAAU,EAAE,SAAS,WAAW,EAAE,CAAC;CACpC;AACD,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,MAAM,GAAG,iBAAiB,GAAG,QAAQ,CAAC;AAQ/E,6FAA6F;AAC7F,MAAM,WAAW,cAAe,SAAQ,eAAe;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE;QACV,aAAa,EAAE,OAAO,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,GAAG,CAAC;QACf,eAAe,EAAE,GAAG,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAQD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAiB/E;AAED,gGAAgG;AAChG,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAY/F;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,oBAAoB,EAAE,KAAK,EAAE,SAAS,cAAc,EAAE,EAAE,OAAO,EAAE;IAClH,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAClE,SAAS,EAAE;QAAE,qBAAqB,EAAE,OAAO,CAAA;KAAE,CAAC;CAC/C;gBA2B4B,MAAM;kBAAgB,MAAM;aAAW,MAAM;aAAW,OAAO;eAAa,MAAM;aAAW,MAAM;YAAU,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,EAAE,CAAC;IAWvK"}
package/dist/providers.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { getAddress, keccak256, toBytes, zeroAddress } from 'viem';
2
2
  import { checkedAddress, getV4PoolId } from './pool.js';
3
+ import { unmodelledV4HookPermissions } from './hooks.js';
3
4
  import { invalid } from './errors.js';
4
5
  const signatures = {
5
6
  Initialize: 'Initialize(bytes32,address,address,uint24,int24,address,uint160,int24)',
@@ -31,6 +32,13 @@ export function verifyV4ProviderDescriptor(provider) {
31
32
  if (!provider.hooks.length)
32
33
  invalid('Provider must enumerate its reviewed hooks');
33
34
  provider.hooks.forEach(checkedAddress);
35
+ if (provider.modelledHookPermissions) {
36
+ for (const hookAddress of provider.hooks) {
37
+ const unmodelled = unmodelledV4HookPermissions(hookAddress, provider.modelledHookPermissions);
38
+ if (unmodelled.length)
39
+ invalid(`Provider hook implements unmodelled permissions: ${unmodelled.join(', ')}`);
40
+ }
41
+ }
34
42
  if (!provider.poolEvents.length || provider.poolEvents.some(event => !Object.hasOwn(signatures, event)))
35
43
  invalid('Explicit supported pool events are required');
36
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAA0B,MAAM,MAAM,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAE,WAAW,EAAwB,MAAM,WAAW,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAqBtC,MAAM,UAAU,GAAgC;IAC9C,UAAU,EAAE,wEAAwE;IACpF,IAAI,EAAE,kEAAkE;IACxE,eAAe,EAAE,6DAA6D;IAC9E,MAAM,EAAE,yCAAyC;CAClD,CAAC;AAgBF,SAAS,IAAI,CAAC,KAAU;IACtB,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,iCAAiC,CAAC,CAAC;AAC9G,CAAC;AACD,SAAS,KAAK,CAAC,KAAa;IAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,CAAC,qCAAqC,CAAC,CAAC;AAC9F,CAAC;AACD,MAAM,UAAU,0BAA0B,CAAC,QAA8B;IACvE,IAAI,QAAQ,CAAC,aAAa,KAAK,CAAC,IAAI,QAAQ,CAAC,SAAS,KAAK,YAAY;QAAE,OAAO,CAAC,uDAAuD,CAAC,CAAC;IAC1I,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,IAAI,EAAE;QAAE,OAAO,CAAC,kDAAkD,CAAC,CAAC;IAChI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,IAAI,CAAC;QAAE,OAAO,CAAC,2BAA2B,CAAC,CAAC;IAC3G,IAAI,cAAc,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,WAAW,IAAI,cAAc,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,WAAW;QAAE,OAAO,CAAC,6CAA6C,CAAC,CAAC;IAC/K,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC3B,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;IACjD,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,eAAe;QAAE,OAAO,CAAC,gDAAgD,CAAC,CAAC;IACxK,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,CAAC,4CAA4C,CAAC,CAAC;IAClF,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACvC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAAE,OAAO,CAAC,6CAA6C,CAAC,CAAC;AAClK,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,oBAAoB,CAAC,QAA8B,EAAE,IAAoB;IACvF,0BAA0B,CAAC,QAAQ,CAAC,CAAC;IACrC,IAAI,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU,IAAI,IAAI,CAAC,YAAY,KAAK,QAAQ,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,OAAO;WAC1H,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,cAAc,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,CAAC,iDAAiD,CAAC,CAAC;IAC3I,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,CAAC,uCAAuC,CAAC,CAAC;IAC5I,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;QAAE,OAAO,CAAC,mCAAmC,CAAC,CAAC;IACpH,IAAI,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,KAAK,cAAc,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC;WAC3F,IAAI,CAAC,UAAU,CAAC,cAAc,KAAK,QAAQ,CAAC,SAAS,CAAC,cAAc;QAAE,OAAO,CAAC,mDAAmD,CAAC,CAAC;IACxI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IACnC,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,GAAG,QAAQ,CAAC,UAAU;QAAE,OAAO,CAAC,qCAAqC,CAAC,CAAC;IACtG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;IACvE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,GAAG,CAAC;QAAE,OAAO,CAAC,8BAA8B,CAAC,CAAC;AAC/H,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,QAA8B,EAAE,KAAgC,EAAE,OAG1G;IACC,0BAA0B,CAAC,QAAQ,CAAC,CAAC;IACrC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,SAAS;QAAE,OAAO,CAAC,kCAAkC,CAAC,CAAC;IACrF,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,qBAAqB;QAAE,OAAO,CAAC,iEAAiE,CAAC,CAAC;IACzH,MAAM,IAAI,GAAG,OAAO,CAAC,oBAAoB,IAAI,EAAE,CAAC;IAChD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,GAAG;QAAE,OAAO,CAAC,kDAAkD,CAAC,CAAC;IACvH,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI;QAAE,OAAO,CAAC,+CAA+C,CAAC,CAAC;IAClF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;IACnD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,oBAAoB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,WAAW,EAAE;eACnG,QAAQ,CAAC,UAAU,CAAC,WAAW,KAAK,IAAI,CAAC,UAAU,CAAC,WAAW;eAC/D,QAAQ,CAAC,UAAU,CAAC,eAAe,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,WAAW,EAAE;eACnG,QAAQ,CAAC,UAAU,CAAC,QAAQ,KAAK,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,CAAC,iFAAiF,CAAC,CAAC;QAC5J,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiB,CAAC;IACxC,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9E,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;QAChH,IAAI,KAAK,GAAG,OAAO,CAAC,OAAO;YAAE,SAAS;QACtC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,EAAS,CAAC,CAAC;QACtB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;IACD,MAAM,KAAK,GAAkK,EAAE,CAAC;IAChL,KAAK,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1F,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,IAAI,IAAI,EAAE,CAAC;YACzD,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC;oBAChE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,YAAY,EAAE,QAAQ,CAAC,YAAY;oBACpE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO;oBACzG,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;iBAClF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { getAddress, keccak256, toBytes, zeroAddress, type Address, type Hex } from 'viem';\nimport { checkedAddress, getV4PoolId, type V4PoolReference } from './pool.js';\nimport { invalid } from './errors.js';\n\n/** Structural contract implemented by protocol SDKs; contains no transport or signer. */\nexport interface V4ProviderDescriptor {\n schemaVersion: 1;\n providerId: string;\n deploymentId: string;\n substrate: 'uniswap-v4';\n chainId: number;\n poolManager: Address;\n startBlock: bigint;\n hooks: readonly Address[];\n discovery: {\n address: Address;\n eventSignature: string;\n poolIdParameter: string;\n expectedRuntimeCodeHash: Hex;\n };\n poolEvents: readonly V4PoolEvent[];\n}\nexport type V4PoolEvent = 'Initialize' | 'Swap' | 'ModifyLiquidity' | 'Donate';\nconst signatures: Record<V4PoolEvent, string> = {\n Initialize: 'Initialize(bytes32,address,address,uint24,int24,address,uint160,int24)',\n Swap: 'Swap(bytes32,address,int128,int128,uint160,uint128,int24,uint24)',\n ModifyLiquidity: 'ModifyLiquidity(bytes32,address,int24,int24,int256,bytes32)',\n Donate: 'Donate(bytes32,address,uint256,uint256)',\n};\n\n/** Evidence is historical, not execution authorization. Protocol SDKs verify its meaning. */\nexport interface V4ProviderPool extends V4PoolReference {\n providerId: string;\n deploymentId: string;\n membership: {\n sourceAddress: Address;\n eventSignature: string;\n blockNumber: bigint;\n blockHash: Hex;\n transactionHash: Hex;\n logIndex: number;\n };\n}\n\nfunction hash(value: Hex) {\n if (!/^0x[\\da-f]{64}$/i.test(value) || /^0x0{64}$/i.test(value)) invalid('Expected a nonzero bytes32 hash');\n}\nfunction block(value: bigint) {\n if (typeof value !== 'bigint' || value < 0n) invalid('Expected a nonnegative block number');\n}\nexport function verifyV4ProviderDescriptor(provider: V4ProviderDescriptor): void {\n if (provider.schemaVersion !== 1 || provider.substrate !== 'uniswap-v4') invalid('Unsupported provider composition version or substrate');\n if (!provider.providerId?.trim() || !provider.deploymentId?.trim()) invalid('Provider and deployment identifiers are required');\n if (!Number.isSafeInteger(provider.chainId) || provider.chainId <= 0) invalid('Invalid provider chain ID');\n if (checkedAddress(provider.poolManager) === zeroAddress || checkedAddress(provider.discovery.address) === zeroAddress) invalid('Provider contracts cannot be zero addresses');\n block(provider.startBlock);\n hash(provider.discovery.expectedRuntimeCodeHash);\n if (!/^[A-Za-z]\\w*\\([^)]*\\)$/.test(provider.discovery.eventSignature) || !provider.discovery.poolIdParameter) invalid('Explicit pool membership discovery is required');\n if (!provider.hooks.length) invalid('Provider must enumerate its reviewed hooks');\n provider.hooks.forEach(checkedAddress);\n if (!provider.poolEvents.length || provider.poolEvents.some(event => !Object.hasOwn(signatures, event))) invalid('Explicit supported pool events are required');\n}\n\n/** Structural/identity verification only; the protocol SDK verifies registration provenance. */\nexport function verifyV4ProviderPool(provider: V4ProviderDescriptor, pool: V4ProviderPool): void {\n verifyV4ProviderDescriptor(provider);\n if (pool.providerId !== provider.providerId || pool.deploymentId !== provider.deploymentId || pool.chainId !== provider.chainId\n || checkedAddress(pool.poolManager) !== checkedAddress(provider.poolManager)) invalid('Pool belongs to a different provider deployment');\n if (!provider.hooks.some(hook => checkedAddress(hook) === checkedAddress(pool.key.hooks))) invalid('Pool uses an unreviewed provider hook');\n if (getV4PoolId(pool.key).toLowerCase() !== pool.poolId.toLowerCase()) invalid('Pool ID differs from its full key');\n if (checkedAddress(pool.membership.sourceAddress) !== checkedAddress(provider.discovery.address)\n || pool.membership.eventSignature !== provider.discovery.eventSignature) invalid('Pool membership uses a different discovery source');\n block(pool.membership.blockNumber);\n if (pool.membership.blockNumber < provider.startBlock) invalid('Pool membership predates deployment');\n hash(pool.membership.blockHash); hash(pool.membership.transactionHash);\n if (!Number.isSafeInteger(pool.membership.logIndex) || pool.membership.logIndex < 0) invalid('Invalid membership log index');\n}\n\n/** Bounded eth_getLogs-compatible plans. Empty selections return no requests, never a wildcard.\n * Hosts must apply topics upstream, retain canonical membership evidence, and replay discovery\n * blocks when the selection changes. Each query covers its whole first block, including events\n * emitted before the registration log. Hosts own reorg rollback, cursors and finality.\n */\nexport function buildV4PoolSubscriptions(provider: V4ProviderDescriptor, pools: readonly V4ProviderPool[], options: {\n fromBlock: bigint; toBlock: bigint; maxPoolIdsPerRequest?: number;\n transport: { indexedTopicFiltering: boolean };\n}) {\n verifyV4ProviderDescriptor(provider);\n block(options.fromBlock); block(options.toBlock);\n if (options.toBlock < options.fromBlock) invalid('Invalid subscription block range');\n if (!options.transport.indexedTopicFiltering) invalid('Selective v4 indexing requires upstream indexed-topic filtering');\n const size = options.maxPoolIdsPerRequest ?? 64;\n if (!Number.isSafeInteger(size) || size < 1 || size > 256) invalid('Pool filter batch size must be between 1 and 256');\n if (pools.length > 4096) invalid('At most 4096 selected pools per planning call');\n const selected = new Map<string, V4ProviderPool>();\n for (const pool of pools) {\n verifyV4ProviderPool(provider, pool);\n const id = pool.poolId.toLowerCase();\n const previous = selected.get(id);\n if (previous && (previous.membership.blockHash.toLowerCase() !== pool.membership.blockHash.toLowerCase()\n || previous.membership.blockNumber !== pool.membership.blockNumber\n || previous.membership.transactionHash.toLowerCase() !== pool.membership.transactionHash.toLowerCase()\n || previous.membership.logIndex !== pool.membership.logIndex)) invalid('Conflicting membership evidence; reconcile canonical history before subscribing');\n selected.set(id, pool);\n }\n const groups = new Map<bigint, Hex[]>();\n for (const [id, pool] of [...selected].sort(([a], [b]) => a.localeCompare(b))) {\n const start = pool.membership.blockNumber > options.fromBlock ? pool.membership.blockNumber : options.fromBlock;\n if (start > options.toBlock) continue;\n const group = groups.get(start) ?? [];\n group.push(id as Hex);\n groups.set(start, group);\n }\n const plans: { providerId: string; deploymentId: string; chainId: number; address: Address; fromBlock: bigint; toBlock: bigint; topics: readonly [Hex, readonly Hex[]] }[] = [];\n for (const [fromBlock, ids] of [...groups].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {\n for (let offset = 0; offset < ids.length; offset += size) {\n for (const event of [...new Set(provider.poolEvents)]) plans.push({\n providerId: provider.providerId, deploymentId: provider.deploymentId,\n chainId: provider.chainId, address: getAddress(provider.poolManager), fromBlock, toBlock: options.toBlock,\n topics: [keccak256(toBytes(signatures[event])), ids.slice(offset, offset + size)],\n });\n }\n }\n return plans;\n}\n"]}
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"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","sourcesContent":["import { getAddress, keccak256, toBytes, zeroAddress, type Address, type Hex } from 'viem';\nimport { checkedAddress, getV4PoolId, type V4PoolReference } from './pool.js';\nimport { unmodelledV4HookPermissions, type V4HookPermissions } from './hooks.js';\nimport { invalid } from './errors.js';\n\n/** Structural contract implemented by protocol SDKs; contains no transport or signer. */\nexport interface V4ProviderDescriptor {\n schemaVersion: 1;\n providerId: string;\n deploymentId: string;\n substrate: 'uniswap-v4';\n chainId: number;\n poolManager: Address;\n startBlock: bigint;\n hooks: readonly Address[];\n /**\n * Permission flags this provider has reviewed across `hooks` — what its hooks\n * are known to do (tax a swap, gate initialization, etc.), not judged here.\n * When present, every hook in `hooks` must implement only these flags, so a\n * provider that has not reviewed a hook's full behaviour cannot silently pass\n * verification once that hook starts using an extra callback. Optional so a\n * provider can adopt this check independently of every other provider.\n */\n modelledHookPermissions?: readonly (keyof V4HookPermissions)[];\n discovery: {\n address: Address;\n eventSignature: string;\n poolIdParameter: string;\n expectedRuntimeCodeHash: Hex;\n };\n poolEvents: readonly V4PoolEvent[];\n}\nexport type V4PoolEvent = 'Initialize' | 'Swap' | 'ModifyLiquidity' | 'Donate';\nconst signatures: Record<V4PoolEvent, string> = {\n Initialize: 'Initialize(bytes32,address,address,uint24,int24,address,uint160,int24)',\n Swap: 'Swap(bytes32,address,int128,int128,uint160,uint128,int24,uint24)',\n ModifyLiquidity: 'ModifyLiquidity(bytes32,address,int24,int24,int256,bytes32)',\n Donate: 'Donate(bytes32,address,uint256,uint256)',\n};\n\n/** Evidence is historical, not execution authorization. Protocol SDKs verify its meaning. */\nexport interface V4ProviderPool extends V4PoolReference {\n providerId: string;\n deploymentId: string;\n membership: {\n sourceAddress: Address;\n eventSignature: string;\n blockNumber: bigint;\n blockHash: Hex;\n transactionHash: Hex;\n logIndex: number;\n };\n}\n\nfunction hash(value: Hex) {\n if (!/^0x[\\da-f]{64}$/i.test(value) || /^0x0{64}$/i.test(value)) invalid('Expected a nonzero bytes32 hash');\n}\nfunction block(value: bigint) {\n if (typeof value !== 'bigint' || value < 0n) invalid('Expected a nonnegative block number');\n}\nexport function verifyV4ProviderDescriptor(provider: V4ProviderDescriptor): void {\n if (provider.schemaVersion !== 1 || provider.substrate !== 'uniswap-v4') invalid('Unsupported provider composition version or substrate');\n if (!provider.providerId?.trim() || !provider.deploymentId?.trim()) invalid('Provider and deployment identifiers are required');\n if (!Number.isSafeInteger(provider.chainId) || provider.chainId <= 0) invalid('Invalid provider chain ID');\n if (checkedAddress(provider.poolManager) === zeroAddress || checkedAddress(provider.discovery.address) === zeroAddress) invalid('Provider contracts cannot be zero addresses');\n block(provider.startBlock);\n hash(provider.discovery.expectedRuntimeCodeHash);\n if (!/^[A-Za-z]\\w*\\([^)]*\\)$/.test(provider.discovery.eventSignature) || !provider.discovery.poolIdParameter) invalid('Explicit pool membership discovery is required');\n if (!provider.hooks.length) invalid('Provider must enumerate its reviewed hooks');\n provider.hooks.forEach(checkedAddress);\n if (provider.modelledHookPermissions) {\n for (const hookAddress of provider.hooks) {\n const unmodelled = unmodelledV4HookPermissions(hookAddress, provider.modelledHookPermissions);\n if (unmodelled.length) invalid(`Provider hook implements unmodelled permissions: ${unmodelled.join(', ')}`);\n }\n }\n if (!provider.poolEvents.length || provider.poolEvents.some(event => !Object.hasOwn(signatures, event))) invalid('Explicit supported pool events are required');\n}\n\n/** Structural/identity verification only; the protocol SDK verifies registration provenance. */\nexport function verifyV4ProviderPool(provider: V4ProviderDescriptor, pool: V4ProviderPool): void {\n verifyV4ProviderDescriptor(provider);\n if (pool.providerId !== provider.providerId || pool.deploymentId !== provider.deploymentId || pool.chainId !== provider.chainId\n || checkedAddress(pool.poolManager) !== checkedAddress(provider.poolManager)) invalid('Pool belongs to a different provider deployment');\n if (!provider.hooks.some(hook => checkedAddress(hook) === checkedAddress(pool.key.hooks))) invalid('Pool uses an unreviewed provider hook');\n if (getV4PoolId(pool.key).toLowerCase() !== pool.poolId.toLowerCase()) invalid('Pool ID differs from its full key');\n if (checkedAddress(pool.membership.sourceAddress) !== checkedAddress(provider.discovery.address)\n || pool.membership.eventSignature !== provider.discovery.eventSignature) invalid('Pool membership uses a different discovery source');\n block(pool.membership.blockNumber);\n if (pool.membership.blockNumber < provider.startBlock) invalid('Pool membership predates deployment');\n hash(pool.membership.blockHash); hash(pool.membership.transactionHash);\n if (!Number.isSafeInteger(pool.membership.logIndex) || pool.membership.logIndex < 0) invalid('Invalid membership log index');\n}\n\n/** Bounded eth_getLogs-compatible plans. Empty selections return no requests, never a wildcard.\n * Hosts must apply topics upstream, retain canonical membership evidence, and replay discovery\n * blocks when the selection changes. Each query covers its whole first block, including events\n * emitted before the registration log. Hosts own reorg rollback, cursors and finality.\n */\nexport function buildV4PoolSubscriptions(provider: V4ProviderDescriptor, pools: readonly V4ProviderPool[], options: {\n fromBlock: bigint; toBlock: bigint; maxPoolIdsPerRequest?: number;\n transport: { indexedTopicFiltering: boolean };\n}) {\n verifyV4ProviderDescriptor(provider);\n block(options.fromBlock); block(options.toBlock);\n if (options.toBlock < options.fromBlock) invalid('Invalid subscription block range');\n if (!options.transport.indexedTopicFiltering) invalid('Selective v4 indexing requires upstream indexed-topic filtering');\n const size = options.maxPoolIdsPerRequest ?? 64;\n if (!Number.isSafeInteger(size) || size < 1 || size > 256) invalid('Pool filter batch size must be between 1 and 256');\n if (pools.length > 4096) invalid('At most 4096 selected pools per planning call');\n const selected = new Map<string, V4ProviderPool>();\n for (const pool of pools) {\n verifyV4ProviderPool(provider, pool);\n const id = pool.poolId.toLowerCase();\n const previous = selected.get(id);\n if (previous && (previous.membership.blockHash.toLowerCase() !== pool.membership.blockHash.toLowerCase()\n || previous.membership.blockNumber !== pool.membership.blockNumber\n || previous.membership.transactionHash.toLowerCase() !== pool.membership.transactionHash.toLowerCase()\n || previous.membership.logIndex !== pool.membership.logIndex)) invalid('Conflicting membership evidence; reconcile canonical history before subscribing');\n selected.set(id, pool);\n }\n const groups = new Map<bigint, Hex[]>();\n for (const [id, pool] of [...selected].sort(([a], [b]) => a.localeCompare(b))) {\n const start = pool.membership.blockNumber > options.fromBlock ? pool.membership.blockNumber : options.fromBlock;\n if (start > options.toBlock) continue;\n const group = groups.get(start) ?? [];\n group.push(id as Hex);\n groups.set(start, group);\n }\n const plans: { providerId: string; deploymentId: string; chainId: number; address: Address; fromBlock: bigint; toBlock: bigint; topics: readonly [Hex, readonly Hex[]] }[] = [];\n for (const [fromBlock, ids] of [...groups].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {\n for (let offset = 0; offset < ids.length; offset += size) {\n for (const event of [...new Set(provider.poolEvents)]) plans.push({\n providerId: provider.providerId, deploymentId: provider.deploymentId,\n chainId: provider.chainId, address: getAddress(provider.poolManager), fromBlock, toBlock: options.toBlock,\n topics: [keccak256(toBytes(signatures[event])), ids.slice(offset, offset + size)],\n });\n }\n }\n return plans;\n}\n"]}
package/dist/v4.d.ts CHANGED
@@ -5,4 +5,6 @@ export type { V4ReadClient, V4Observation, V4PoolSnapshot, V4QuoteInput, V4Quote
5
5
  export { readV4TickWindow, ticksInWord } from './depth.js';
6
6
  export type { V4Tick, V4TickWindow } from './depth.js';
7
7
  export { decodeV4PoolInitialization } from './events.js';
8
+ export { decodeV4HookPermissions, unmodelledV4HookPermissions } from './hooks.js';
9
+ export type { V4HookPermissions } from './hooks.js';
8
10
  //# sourceMappingURL=v4.d.ts.map
package/dist/v4.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"v4.d.ts","sourceRoot":"","sources":["../src/v4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC9E,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACnG,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACpH,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC3D,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"v4.d.ts","sourceRoot":"","sources":["../src/v4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC9E,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACnG,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACpH,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC3D,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAClF,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
package/dist/v4.js CHANGED
@@ -2,4 +2,5 @@ export { poolKeyFromCurrencies, getV4PoolId, poolReference } from './pool.js';
2
2
  export { readV4Pool, quoteV4ExactInput, quoteV4Batch, verifyV4DeploymentWiring } from './reads.js';
3
3
  export { readV4TickWindow, ticksInWord } from './depth.js';
4
4
  export { decodeV4PoolInitialization } from './events.js';
5
+ export { decodeV4HookPermissions, unmodelledV4HookPermissions } from './hooks.js';
5
6
  //# sourceMappingURL=v4.js.map
package/dist/v4.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"v4.js","sourceRoot":"","sources":["../src/v4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE9E,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEnG,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC","sourcesContent":["export { poolKeyFromCurrencies, getV4PoolId, poolReference } from './pool.js';\nexport type { V4Deployment, V4PoolKey, V4PoolReference } from './pool.js';\nexport { readV4Pool, quoteV4ExactInput, quoteV4Batch, verifyV4DeploymentWiring } from './reads.js';\nexport type { V4ReadClient, V4Observation, V4PoolSnapshot, V4QuoteInput, V4Quote, V4QuoteResult } from './reads.js';\nexport { readV4TickWindow, ticksInWord } from './depth.js';\nexport type { V4Tick, V4TickWindow } from './depth.js';\nexport { decodeV4PoolInitialization } from './events.js';\n"]}
1
+ {"version":3,"file":"v4.js","sourceRoot":"","sources":["../src/v4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE9E,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEnG,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC","sourcesContent":["export { poolKeyFromCurrencies, getV4PoolId, poolReference } from './pool.js';\nexport type { V4Deployment, V4PoolKey, V4PoolReference } from './pool.js';\nexport { readV4Pool, quoteV4ExactInput, quoteV4Batch, verifyV4DeploymentWiring } from './reads.js';\nexport type { V4ReadClient, V4Observation, V4PoolSnapshot, V4QuoteInput, V4Quote, V4QuoteResult } from './reads.js';\nexport { readV4TickWindow, ticksInWord } from './depth.js';\nexport type { V4Tick, V4TickWindow } from './depth.js';\nexport { decodeV4PoolInitialization } from './events.js';\nexport { decodeV4HookPermissions, unmodelledV4HookPermissions } from './hooks.js';\nexport type { V4HookPermissions } from './hooks.js';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reptilianhq/uniswap-sdk",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "Deployment-explicit Uniswap observations and reviewed transaction material.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -119,6 +119,6 @@
119
119
  "reptilianRelease": {
120
120
  "schemaVersion": 1,
121
121
  "group": "uniswap-sdk",
122
- "sourceSha": "d02bfdd8f80b6f95c7fc573ccd4eb17e6de6a0cf"
122
+ "sourceSha": "5f41e24057e8865a6df61ba4c13c0272a870e4a3"
123
123
  }
124
124
  }