@reptilianhq/uniswap-sdk 0.4.0 → 0.6.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.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Percent = exports.V4PositionManager = exports.Position = exports.Hook = exports.Pool = void 0;
3
+ exports.permit2Address = exports.AllowanceTransfer = exports.Percent = exports.V4PositionManager = exports.Position = 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.
@@ -11,4 +11,7 @@ Object.defineProperty(exports, "Position", { enumerable: true, get: function ()
11
11
  Object.defineProperty(exports, "V4PositionManager", { enumerable: true, get: function () { return v4_sdk_1.V4PositionManager; } });
12
12
  var sdk_core_1 = require("@uniswap/sdk-core");
13
13
  Object.defineProperty(exports, "Percent", { enumerable: true, get: function () { return sdk_core_1.Percent; } });
14
+ var permit2_sdk_1 = require("@uniswap/permit2-sdk");
15
+ Object.defineProperty(exports, "AllowanceTransfer", { enumerable: true, get: function () { return permit2_sdk_1.AllowanceTransfer; } });
16
+ Object.defineProperty(exports, "permit2Address", { enumerable: true, get: function () { return permit2_sdk_1.permit2Address; } });
14
17
  //# 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,0CAA0E;AAAjE,8FAAA,IAAI,OAAA;AAAE,8FAAA,IAAI,OAAA;AAAE,kGAAA,QAAQ,OAAA;AAAE,2GAAA,iBAAiB,OAAA;AAChD,8CAA4C;AAAnC,mGAAA,OAAO,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, Position, V4PositionManager } from '@uniswap/v4-sdk';\nexport { Percent } from '@uniswap/sdk-core';\n"]}
1
+ {"version":3,"file":"official-sdk.cjs","sourceRoot":"","sources":["../src/official-sdk.cts"],"names":[],"mappings":";;;AAAA,4EAA4E;AAC5E,0EAA0E;AAC1E,2EAA2E;AAC3E,0CAA0E;AAAjE,8FAAA,IAAI,OAAA;AAAE,8FAAA,IAAI,OAAA;AAAE,kGAAA,QAAQ,OAAA;AAAE,2GAAA,iBAAiB,OAAA;AAChD,8CAA4C;AAAnC,mGAAA,OAAO,OAAA;AAChB,oDAAyE;AAAhE,gHAAA,iBAAiB,OAAA;AAAE,6GAAA,cAAc,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, Position, V4PositionManager } from '@uniswap/v4-sdk';\nexport { Percent } from '@uniswap/sdk-core';\nexport { AllowanceTransfer, permit2Address } from '@uniswap/permit2-sdk';\n"]}
@@ -1,3 +1,4 @@
1
1
  export { Pool, Hook, Position, V4PositionManager } from '@uniswap/v4-sdk';
2
2
  export { Percent } from '@uniswap/sdk-core';
3
+ export { AllowanceTransfer, permit2Address } from '@uniswap/permit2-sdk';
3
4
  //# 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,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"official-sdk.d.cts","sourceRoot":"","sources":["../src/official-sdk.cts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,62 @@
1
+ import type { Address } from 'viem';
2
+ export type V4PermitBatchDetailInput = {
3
+ token: Address;
4
+ amount: bigint;
5
+ expiration: bigint;
6
+ nonce: bigint;
7
+ };
8
+ export type V4PermitBatchTypedData = {
9
+ domain: {
10
+ name: 'Permit2';
11
+ chainId: number;
12
+ verifyingContract: Address;
13
+ };
14
+ types: {
15
+ PermitBatch: readonly {
16
+ name: string;
17
+ type: string;
18
+ }[];
19
+ PermitDetails: readonly {
20
+ name: string;
21
+ type: string;
22
+ }[];
23
+ };
24
+ primaryType: 'PermitBatch';
25
+ message: {
26
+ details: readonly {
27
+ token: Address;
28
+ amount: bigint;
29
+ expiration: bigint;
30
+ nonce: bigint;
31
+ }[];
32
+ spender: Address;
33
+ sigDeadline: bigint;
34
+ };
35
+ };
36
+ /**
37
+ * Builds the EIP-712 typed data for a caller's wallet to sign, authorizing PositionManager
38
+ * to pull the tokens a v4 mint needs via Permit2's `AllowanceTransfer.permitBatch`, instead
39
+ * of a prior plain ERC20 `approve`. This SDK never holds a signer — the caller signs this
40
+ * with their own wallet (`eth_signTypedData_v4`) and passes the resulting signature on to
41
+ * whatever assembles the mint's `batchPermit` option; encoding that consumption side is a
42
+ * separate, later piece.
43
+ *
44
+ * Delegates the domain and EIP-712 type definitions to `@uniswap/permit2-sdk`'s
45
+ * `AllowanceTransfer.getPermitData` rather than hand-authoring them: Permit2's typed-data
46
+ * schema lives only in its deployed contract, and no vendored Uniswap SDK re-derives it —
47
+ * getting it wrong produces a signature that fails silently on-chain, not a caught error.
48
+ *
49
+ * `spender` is trusted as given — this function does not know what contract the caller
50
+ * intends to grant to. Callers must pass PositionManager's own address, not a value taken
51
+ * from unreviewed input; a wrong `spender` here authorizes an arbitrary contract to pull
52
+ * the caller's tokens, and this SDK has no way to detect that from the typed data alone.
53
+ */
54
+ export declare function buildV4MintPermitBatchTypedData(input: {
55
+ chainId: number;
56
+ spender: Address;
57
+ details: readonly V4PermitBatchDetailInput[];
58
+ sigDeadline: bigint;
59
+ /** Overrides the canonical per-chain Permit2 deployment; only for a non-standard deployment. */
60
+ permit2Address?: Address;
61
+ }): V4PermitBatchTypedData;
62
+ //# sourceMappingURL=permit2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permit2.d.ts","sourceRoot":"","sources":["../src/permit2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAMpC,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,OAAO,CAAA;KAAE,CAAC;IACzE,KAAK,EAAE;QACL,WAAW,EAAE,SAAS;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QACvD,aAAa,EAAE,SAAS;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KAC1D,CAAC;IACF,WAAW,EAAE,aAAa,CAAC;IAC3B,OAAO,EAAE;QACP,OAAO,EAAE,SAAS;YAAE,KAAK,EAAE,OAAO,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAC1F,OAAO,EAAE,OAAO,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH,CAAC;AAYF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,SAAS,wBAAwB,EAAE,CAAC;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,GAAG,sBAAsB,CA+CzB"}
@@ -0,0 +1,81 @@
1
+ import { zeroAddress } from 'viem';
2
+ import { AllowanceTransfer, permit2Address } from './official-sdk.cjs';
3
+ import { checkedAddress } from './pool.js';
4
+ import { invalid, UniswapSdkError } from './errors.js';
5
+ function nonNegative(value, label) {
6
+ if (value < 0n)
7
+ invalid(`${label} must not be negative`);
8
+ }
9
+ function nonZeroAddress(value, label) {
10
+ const checked = checkedAddress(value);
11
+ if (checked === zeroAddress)
12
+ invalid(`${label} cannot be the zero address`);
13
+ return checked;
14
+ }
15
+ /**
16
+ * Builds the EIP-712 typed data for a caller's wallet to sign, authorizing PositionManager
17
+ * to pull the tokens a v4 mint needs via Permit2's `AllowanceTransfer.permitBatch`, instead
18
+ * of a prior plain ERC20 `approve`. This SDK never holds a signer — the caller signs this
19
+ * with their own wallet (`eth_signTypedData_v4`) and passes the resulting signature on to
20
+ * whatever assembles the mint's `batchPermit` option; encoding that consumption side is a
21
+ * separate, later piece.
22
+ *
23
+ * Delegates the domain and EIP-712 type definitions to `@uniswap/permit2-sdk`'s
24
+ * `AllowanceTransfer.getPermitData` rather than hand-authoring them: Permit2's typed-data
25
+ * schema lives only in its deployed contract, and no vendored Uniswap SDK re-derives it —
26
+ * getting it wrong produces a signature that fails silently on-chain, not a caught error.
27
+ *
28
+ * `spender` is trusted as given — this function does not know what contract the caller
29
+ * intends to grant to. Callers must pass PositionManager's own address, not a value taken
30
+ * from unreviewed input; a wrong `spender` here authorizes an arbitrary contract to pull
31
+ * the caller's tokens, and this SDK has no way to detect that from the typed data alone.
32
+ */
33
+ export function buildV4MintPermitBatchTypedData(input) {
34
+ if (!Number.isSafeInteger(input.chainId) || input.chainId <= 0)
35
+ invalid('chainId must be a positive safe integer');
36
+ if (!input.details.length)
37
+ invalid('Permit batch must include at least one token detail');
38
+ nonNegative(input.sigDeadline, 'sigDeadline');
39
+ const spender = nonZeroAddress(input.spender, 'spender');
40
+ const resolvedPermit2Address = nonZeroAddress(input.permit2Address ?? permit2Address(input.chainId), 'permit2Address');
41
+ try {
42
+ const details = input.details.map(detail => {
43
+ nonNegative(detail.amount, 'amount');
44
+ nonNegative(detail.expiration, 'expiration');
45
+ nonNegative(detail.nonce, 'nonce');
46
+ return {
47
+ token: checkedAddress(detail.token),
48
+ amount: detail.amount.toString(),
49
+ expiration: detail.expiration.toString(),
50
+ nonce: detail.nonce.toString(),
51
+ };
52
+ });
53
+ const { domain, types, values } = AllowanceTransfer.getPermitData({ details, spender, sigDeadline: input.sigDeadline.toString() }, resolvedPermit2Address, input.chainId);
54
+ const batch = values;
55
+ if (domain.name !== 'Permit2')
56
+ invalid(`Official Permit2 SDK returned an unexpected domain name: ${String(domain.name)}`);
57
+ return {
58
+ domain: { name: 'Permit2', chainId: domain.chainId, verifyingContract: checkedAddress(domain.verifyingContract) },
59
+ // Deep-copied: `types` is the dependency's own module-level object: mutating the
60
+ // returned value would otherwise corrupt every future call in this process.
61
+ types: structuredClone(types),
62
+ primaryType: 'PermitBatch',
63
+ message: {
64
+ details: batch.details.map(detail => ({
65
+ token: checkedAddress(detail.token),
66
+ amount: BigInt(detail.amount),
67
+ expiration: BigInt(detail.expiration),
68
+ nonce: BigInt(detail.nonce),
69
+ })),
70
+ spender: checkedAddress(batch.spender),
71
+ sigDeadline: BigInt(batch.sigDeadline),
72
+ },
73
+ };
74
+ }
75
+ catch (cause) {
76
+ if (cause instanceof UniswapSdkError)
77
+ throw cause;
78
+ throw new UniswapSdkError('INVALID_ARGUMENT', 'Official Permit2 SDK rejected the permit batch parameters', { cause });
79
+ }
80
+ }
81
+ //# sourceMappingURL=permit2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permit2.js","sourceRoot":"","sources":["../src/permit2.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Address } from 'viem';\nimport { zeroAddress } from 'viem';\nimport { AllowanceTransfer, permit2Address } from './official-sdk.cjs';\nimport { checkedAddress } from './pool.js';\nimport { invalid, UniswapSdkError } from './errors.js';\n\nexport type V4PermitBatchDetailInput = {\n token: Address;\n amount: bigint;\n expiration: bigint;\n nonce: bigint;\n};\n\nexport type V4PermitBatchTypedData = {\n domain: { name: 'Permit2'; chainId: number; verifyingContract: Address };\n types: {\n PermitBatch: readonly { name: string; type: string }[];\n PermitDetails: readonly { name: string; type: string }[];\n };\n primaryType: 'PermitBatch';\n message: {\n details: readonly { token: Address; amount: bigint; expiration: bigint; nonce: bigint }[];\n spender: Address;\n sigDeadline: bigint;\n };\n};\n\nfunction nonNegative(value: bigint, label: string): void {\n if (value < 0n) invalid(`${label} must not be negative`);\n}\n\nfunction nonZeroAddress(value: Address, label: string): Address {\n const checked = checkedAddress(value);\n if (checked === zeroAddress) invalid(`${label} cannot be the zero address`);\n return checked;\n}\n\n/**\n * Builds the EIP-712 typed data for a caller's wallet to sign, authorizing PositionManager\n * to pull the tokens a v4 mint needs via Permit2's `AllowanceTransfer.permitBatch`, instead\n * of a prior plain ERC20 `approve`. This SDK never holds a signer — the caller signs this\n * with their own wallet (`eth_signTypedData_v4`) and passes the resulting signature on to\n * whatever assembles the mint's `batchPermit` option; encoding that consumption side is a\n * separate, later piece.\n *\n * Delegates the domain and EIP-712 type definitions to `@uniswap/permit2-sdk`'s\n * `AllowanceTransfer.getPermitData` rather than hand-authoring them: Permit2's typed-data\n * schema lives only in its deployed contract, and no vendored Uniswap SDK re-derives it —\n * getting it wrong produces a signature that fails silently on-chain, not a caught error.\n *\n * `spender` is trusted as given — this function does not know what contract the caller\n * intends to grant to. Callers must pass PositionManager's own address, not a value taken\n * from unreviewed input; a wrong `spender` here authorizes an arbitrary contract to pull\n * the caller's tokens, and this SDK has no way to detect that from the typed data alone.\n */\nexport function buildV4MintPermitBatchTypedData(input: {\n chainId: number;\n spender: Address;\n details: readonly V4PermitBatchDetailInput[];\n sigDeadline: bigint;\n /** Overrides the canonical per-chain Permit2 deployment; only for a non-standard deployment. */\n permit2Address?: Address;\n}): V4PermitBatchTypedData {\n if (!Number.isSafeInteger(input.chainId) || input.chainId <= 0) invalid('chainId must be a positive safe integer');\n if (!input.details.length) invalid('Permit batch must include at least one token detail');\n nonNegative(input.sigDeadline, 'sigDeadline');\n const spender = nonZeroAddress(input.spender, 'spender');\n const resolvedPermit2Address = nonZeroAddress(input.permit2Address ?? (permit2Address(input.chainId) as Address), 'permit2Address');\n\n try {\n const details = input.details.map(detail => {\n nonNegative(detail.amount, 'amount');\n nonNegative(detail.expiration, 'expiration');\n nonNegative(detail.nonce, 'nonce');\n return {\n token: checkedAddress(detail.token),\n amount: detail.amount.toString(),\n expiration: detail.expiration.toString(),\n nonce: detail.nonce.toString(),\n };\n });\n const { domain, types, values } = AllowanceTransfer.getPermitData(\n { details, spender, sigDeadline: input.sigDeadline.toString() },\n resolvedPermit2Address,\n input.chainId,\n );\n const batch = values as { details: { token: string; amount: string; expiration: string; nonce: string }[]; spender: string; sigDeadline: string };\n if (domain.name !== 'Permit2') invalid(`Official Permit2 SDK returned an unexpected domain name: ${String(domain.name)}`);\n return {\n domain: { name: 'Permit2', chainId: domain.chainId as number, verifyingContract: checkedAddress(domain.verifyingContract as Address) },\n // Deep-copied: `types` is the dependency's own module-level object: mutating the\n // returned value would otherwise corrupt every future call in this process.\n types: structuredClone(types) as unknown as V4PermitBatchTypedData['types'],\n primaryType: 'PermitBatch',\n message: {\n details: batch.details.map(detail => ({\n token: checkedAddress(detail.token as Address),\n amount: BigInt(detail.amount),\n expiration: BigInt(detail.expiration),\n nonce: BigInt(detail.nonce),\n })),\n spender: checkedAddress(batch.spender as Address),\n sigDeadline: BigInt(batch.sigDeadline),\n },\n };\n } catch (cause) {\n if (cause instanceof UniswapSdkError) throw cause;\n throw new UniswapSdkError('INVALID_ARGUMENT', 'Official Permit2 SDK rejected the permit batch parameters', { cause });\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { Currency } from '@uniswap/sdk-core';
2
- import type { Address, Hex } from 'viem';
2
+ import { type Address, type Hex } from 'viem';
3
3
  export type V4TransactionMaterial = {
4
4
  to: Address;
5
5
  data: Hex;
@@ -44,4 +44,54 @@ export type V4MintPositionParams = {
44
44
  * responsibility; this function only encodes what it is given.
45
45
  */
46
46
  export declare function buildV4MintPositionTransaction(input: V4MintPositionParams): V4TransactionMaterial;
47
+ export type V4PoolKeyMaterial = {
48
+ currency0: Address;
49
+ currency1: Address;
50
+ fee: number;
51
+ tickSpacing: number;
52
+ hooks: Address;
53
+ };
54
+ export type V4MintActionParams = {
55
+ poolKey: V4PoolKeyMaterial;
56
+ tickLower: number;
57
+ tickUpper: number;
58
+ liquidity: bigint;
59
+ amount0Max: bigint;
60
+ amount1Max: bigint;
61
+ owner: Address;
62
+ hookData: Hex;
63
+ deadline: bigint;
64
+ /** Present only if this mint atomically initializes the pool; the price it initializes at. */
65
+ createdAtSqrtPriceX96?: bigint;
66
+ };
67
+ export type V4ExpectedMint = V4PoolKeyMaterial & {
68
+ recipient: Address;
69
+ /**
70
+ * Required if this mint might atomically create the pool; the only price that
71
+ * mint may set. Checked only in that direction: supplying it does not require
72
+ * the calldata to actually create the pool — a plain mint into an
73
+ * already-initialized pool is unaffected either way, distinguishable from a
74
+ * pool-creating mint by `createdAtSqrtPriceX96` being absent from the result.
75
+ */
76
+ sqrtPriceX96?: bigint;
77
+ };
78
+ /**
79
+ * Decodes and verifies calldata built by `buildV4MintPositionTransaction`: a
80
+ * `modifyLiquidities` call — optionally wrapped in a `multicall` alongside pool
81
+ * initialization — encoding exactly a MINT_POSITION action, a SETTLE_PAIR, and,
82
+ * for a native-currency0 mint, a trailing SWEEP. This is the only action shape
83
+ * that function produces; any other sequence is calldata this decoder does not
84
+ * recognise as its own and refuses, rather than guessing at its meaning.
85
+ *
86
+ * `expected` must name the full pool (including `hooks`), not just the token
87
+ * pair — a mint into the same pair through a different, unreviewed hook is a
88
+ * different pool with different economics, not a cosmetic difference.
89
+ * `currency0`/`currency1` must already be in canonical (sorted) order, and a
90
+ * native-currency pool's `currency0` must be the zero address, matching how
91
+ * `V4PoolKey`/`Pool` represent it elsewhere in this SDK — this function does
92
+ * not reorder or reinterpret them. Pass `sqrtPriceX96` when the mint might
93
+ * atomically create the pool; omitting it fails closed rather than silently
94
+ * accepting whatever starting price the calldata sets.
95
+ */
96
+ export declare function reviewV4MintPositionCalldata(data: Hex, expected: V4ExpectedMint): V4MintActionParams;
47
97
  //# sourceMappingURL=v4-transactions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"v4-transactions.d.ts","sourceRoot":"","sources":["../src/v4-transactions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAKzC,MAAM,MAAM,qBAAqB,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9E,oGAAoG;AACpG,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,EAAE,QAAQ,CAAC;IACpB,SAAS,EAAE,QAAQ,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,sHAAsH;IACtH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AASF;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CAyCjG"}
1
+ {"version":3,"file":"v4-transactions.d.ts","sourceRoot":"","sources":["../src/v4-transactions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAA4E,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAMxH,MAAM,MAAM,qBAAqB,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9E,oGAAoG;AACpG,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,EAAE,QAAQ,CAAC;IACpB,SAAS,EAAE,QAAQ,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,sHAAsH;IACtH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AASF;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CAyCjG;AAgBD,MAAM,MAAM,iBAAiB,GAAG;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAC7H,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,8FAA8F;IAC9F,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAwBF,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,cAAc,GAAG,kBAAkB,CAsEpG"}
@@ -1,6 +1,8 @@
1
+ import { decodeAbiParameters, decodeFunctionData, parseAbiParameters, zeroAddress } from 'viem';
1
2
  import { Percent, Pool, Position, V4PositionManager } from './official-sdk.cjs';
2
3
  import { checkedAddress } from './pool.js';
3
4
  import { invalid, UniswapSdkError } from './errors.js';
5
+ import { v4PositionManagerAbi } from './abis.js';
4
6
  function slippagePercent(bps) {
5
7
  if (!Number.isInteger(bps) || bps < 0 || bps > 10_000) {
6
8
  invalid('slippageToleranceBps must be an integer between 0 and 10000');
@@ -54,4 +56,125 @@ export function buildV4MintPositionTransaction(input) {
54
56
  throw new UniswapSdkError('INVALID_ARGUMENT', 'Official Uniswap SDK rejected the mint parameters', { cause });
55
57
  }
56
58
  }
59
+ const MINT_POSITION_ACTION = 2;
60
+ const SETTLE_PAIR_ACTION = 13;
61
+ const SWEEP_ACTION = 20;
62
+ /** PositionManager's `msgSender()` sentinel; the only address `SWEEP` may refund to. */
63
+ const MSG_SENDER = '0x0000000000000000000000000000000000000001';
64
+ const unlockDataParams = parseAbiParameters('bytes actions, bytes[] params');
65
+ const poolKeyStruct = '(address currency0, address currency1, uint24 fee, int24 tickSpacing, address hooks)';
66
+ const mintPositionParams = parseAbiParameters(`${poolKeyStruct} poolKey, int24 tickLower, int24 tickUpper, uint256 liquidity, uint128 amount0Max, uint128 amount1Max, address owner, bytes hookData`);
67
+ const settlePairParams = parseAbiParameters('address currency0, address currency1');
68
+ const sweepParams = parseAbiParameters('address currency, address to');
69
+ function same(a, b) {
70
+ return a.toLowerCase() === b.toLowerCase();
71
+ }
72
+ function mismatch(message) {
73
+ throw new UniswapSdkError('CALLDATA_MISMATCH', message);
74
+ }
75
+ /** `bytes actions` packs one uint8 opcode per action, two hex characters each. */
76
+ function decodeActionIds(actions) {
77
+ const hex = actions.slice(2);
78
+ if (hex.length % 2 !== 0)
79
+ mismatch('Mint calldata has a malformed action byte string');
80
+ const ids = [];
81
+ for (let i = 0; i < hex.length; i += 2)
82
+ ids.push(parseInt(hex.slice(i, i + 2), 16));
83
+ return ids;
84
+ }
85
+ function samePoolKey(a, b) {
86
+ return same(a.currency0, b.currency0) && same(a.currency1, b.currency1)
87
+ && a.fee === b.fee && a.tickSpacing === b.tickSpacing && same(a.hooks, b.hooks);
88
+ }
89
+ /**
90
+ * Decodes and verifies calldata built by `buildV4MintPositionTransaction`: a
91
+ * `modifyLiquidities` call — optionally wrapped in a `multicall` alongside pool
92
+ * initialization — encoding exactly a MINT_POSITION action, a SETTLE_PAIR, and,
93
+ * for a native-currency0 mint, a trailing SWEEP. This is the only action shape
94
+ * that function produces; any other sequence is calldata this decoder does not
95
+ * recognise as its own and refuses, rather than guessing at its meaning.
96
+ *
97
+ * `expected` must name the full pool (including `hooks`), not just the token
98
+ * pair — a mint into the same pair through a different, unreviewed hook is a
99
+ * different pool with different economics, not a cosmetic difference.
100
+ * `currency0`/`currency1` must already be in canonical (sorted) order, and a
101
+ * native-currency pool's `currency0` must be the zero address, matching how
102
+ * `V4PoolKey`/`Pool` represent it elsewhere in this SDK — this function does
103
+ * not reorder or reinterpret them. Pass `sqrtPriceX96` when the mint might
104
+ * atomically create the pool; omitting it fails closed rather than silently
105
+ * accepting whatever starting price the calldata sets.
106
+ */
107
+ export function reviewV4MintPositionCalldata(data, expected) {
108
+ try {
109
+ const decoded = decodeFunctionData({ abi: v4PositionManagerAbi, data });
110
+ let unlockData;
111
+ let deadline;
112
+ let initialization;
113
+ if (decoded.functionName === 'multicall') {
114
+ const calls = decoded.args[0].map(call => decodeFunctionData({ abi: v4PositionManagerAbi, data: call }));
115
+ if (calls.length !== 2 || calls[0].functionName !== 'initializePool' || calls[1].functionName !== 'modifyLiquidities') {
116
+ mismatch('Mint calldata multicall must contain only pool initialization followed by one mint');
117
+ }
118
+ initialization = { key: calls[0].args[0], sqrtPriceX96: calls[0].args[1] };
119
+ [unlockData, deadline] = calls[1].args;
120
+ }
121
+ else if (decoded.functionName === 'modifyLiquidities') {
122
+ [unlockData, deadline] = decoded.args;
123
+ }
124
+ else {
125
+ return mismatch('Mint calldata is not a position-manager modifyLiquidities call');
126
+ }
127
+ const [actionsBytes, actionParams] = decodeAbiParameters(unlockDataParams, unlockData);
128
+ const actionIds = decodeActionIds(actionsBytes);
129
+ if (actionIds.length !== actionParams.length)
130
+ mismatch('Mint calldata has a different number of actions and action parameters');
131
+ if (actionIds.length < 2 || actionIds.length > 3)
132
+ mismatch('Mint calldata does not have the action count a plain mint produces');
133
+ if (actionIds[0] !== MINT_POSITION_ACTION)
134
+ mismatch('Mint calldata must begin with a MINT_POSITION action');
135
+ const [poolKey, tickLower, tickUpper, liquidity, amount0Max, amount1Max, owner, hookData] = decodeAbiParameters(mintPositionParams, actionParams[0]);
136
+ if (liquidity <= 0n)
137
+ mismatch('Mint calldata mints non-positive liquidity');
138
+ if (initialization && !samePoolKey(initialization.key, poolKey)) {
139
+ mismatch('Mint pool initialization targets a different pool than the position mint');
140
+ }
141
+ if (actionIds[1] !== SETTLE_PAIR_ACTION)
142
+ mismatch('MINT_POSITION must be followed by a SETTLE_PAIR');
143
+ const [settleCurrency0, settleCurrency1] = decodeAbiParameters(settlePairParams, actionParams[1]);
144
+ if (!same(settleCurrency0, poolKey.currency0) || !same(settleCurrency1, poolKey.currency1)) {
145
+ mismatch('SETTLE_PAIR settles a different pair than the minted position');
146
+ }
147
+ if (actionIds.length === 3) {
148
+ if (actionIds[2] !== SWEEP_ACTION)
149
+ mismatch('Mint calldata has an unreviewed action after SETTLE_PAIR');
150
+ const [sweepCurrency, sweepTo] = decodeAbiParameters(sweepParams, actionParams[2]);
151
+ if (!same(sweepCurrency, zeroAddress) && !same(sweepCurrency, poolKey.currency0)) {
152
+ mismatch('SWEEP refunds an unexpected currency');
153
+ }
154
+ if (!same(sweepTo, MSG_SENDER))
155
+ mismatch('SWEEP sends the refund to an unexpected recipient');
156
+ }
157
+ if (!samePoolKey(poolKey, expected))
158
+ mismatch('Mint calldata targets a different pool than expected');
159
+ if (!same(owner, expected.recipient))
160
+ mismatch('Mint calldata sends the position NFT to a different recipient');
161
+ if (initialization) {
162
+ if (expected.sqrtPriceX96 === undefined) {
163
+ mismatch('Mint calldata initializes the pool but no expected starting price was supplied to verify it');
164
+ }
165
+ if (initialization.sqrtPriceX96 !== expected.sqrtPriceX96) {
166
+ mismatch('Mint calldata initializes the pool at a different starting price than expected');
167
+ }
168
+ }
169
+ return {
170
+ poolKey, tickLower, tickUpper, liquidity, amount0Max, amount1Max, owner, hookData, deadline,
171
+ ...(initialization ? { createdAtSqrtPriceX96: initialization.sqrtPriceX96 } : {}),
172
+ };
173
+ }
174
+ catch (error) {
175
+ if (error instanceof UniswapSdkError)
176
+ throw error;
177
+ throw new UniswapSdkError('CALLDATA_MISMATCH', 'Mint calldata contains undecodable position-manager calls', { cause: error });
178
+ }
179
+ }
57
180
  //# sourceMappingURL=v4-transactions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"v4-transactions.js","sourceRoot":"","sources":["../src/v4-transactions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Currency } from '@uniswap/sdk-core';\nimport type { Address, Hex } from 'viem';\nimport { Percent, Pool, Position, V4PositionManager } from './official-sdk.cjs';\nimport { checkedAddress } from './pool.js';\nimport { invalid, UniswapSdkError } from './errors.js';\n\nexport type V4TransactionMaterial = { to: Address; data: Hex; value: bigint };\n\n/** Pool state as read from PoolManager/StateView (e.g. via `readV4Pool`), not yet a mint target. */\nexport type V4PoolState = {\n currency0: Currency;\n currency1: Currency;\n fee: number;\n tickSpacing: number;\n hooks: Address;\n sqrtPriceX96: bigint;\n liquidity: bigint;\n tickCurrent: number;\n};\n\nexport type V4MintPositionParams = {\n positionManager: Address;\n pool: V4PoolState;\n tickLower: number;\n tickUpper: number;\n /** Liquidity units to mint, not a token amount. */\n liquidity: bigint;\n recipient: Address;\n /** Integer basis points, 0-10000. */\n slippageToleranceBps: number;\n deadlineSeconds: bigint;\n /** Passed to the hook's callbacks verbatim; this SDK does not construct it. */\n hookData?: Hex;\n /** Atomically initializes the pool before minting. Requires `pool.sqrtPriceX96` to be the intended starting price. */\n createPool?: boolean;\n};\n\nfunction slippagePercent(bps: number): Percent {\n if (!Number.isInteger(bps) || bps < 0 || bps > 10_000) {\n invalid('slippageToleranceBps must be an integer between 0 and 10000');\n }\n return new Percent(bps, 10_000);\n}\n\n/**\n * Builds unsigned calldata for `PositionManager.modifyLiquidities` minting a new v4 position.\n * Delegates encoding to `@uniswap/v4-sdk`'s `V4PositionManager`/`V4PositionPlanner` (the same\n * Actions/multicall encoding Uniswap's own SDK uses) rather than hand-rolling it, since v4's\n * calldata is a sequence of packed actions, not a single ABI-encoded function call like v3's.\n *\n * No Permit2 support yet — callers must have already approved the position manager via a plain\n * ERC20 approval, or the built transaction will revert on-chain. Hook-permission gating (refusing\n * a pool whose hook implements more than the caller has modelled) is also the caller's\n * responsibility; this function only encodes what it is given.\n */\nexport function buildV4MintPositionTransaction(input: V4MintPositionParams): V4TransactionMaterial {\n if (input.liquidity <= 0n) invalid('Mint liquidity must be positive');\n if (!Number.isInteger(input.tickLower) || !Number.isInteger(input.tickUpper) || input.tickLower >= input.tickUpper) {\n invalid('tickLower must be an integer less than tickUpper');\n }\n if (input.createPool && input.pool.sqrtPriceX96 <= 0n) invalid('createPool requires a positive initial sqrtPriceX96');\n const positionManager = checkedAddress(input.positionManager);\n const recipient = checkedAddress(input.recipient);\n const slippageTolerance = slippagePercent(input.slippageToleranceBps);\n\n try {\n const pool = new Pool(\n input.pool.currency0,\n input.pool.currency1,\n input.pool.fee,\n input.pool.tickSpacing,\n checkedAddress(input.pool.hooks),\n input.pool.sqrtPriceX96.toString(),\n input.pool.liquidity.toString(),\n input.pool.tickCurrent,\n );\n const position = new Position({\n pool,\n liquidity: input.liquidity.toString(),\n tickLower: input.tickLower,\n tickUpper: input.tickUpper,\n });\n const params = V4PositionManager.addCallParameters(position, {\n recipient,\n createPool: input.createPool ?? false,\n ...(input.createPool ? { sqrtPriceX96: input.pool.sqrtPriceX96.toString() } : {}),\n useNative: pool.currency0.isNative ? pool.currency0 : undefined,\n slippageTolerance,\n hookData: input.hookData,\n deadline: input.deadlineSeconds.toString(),\n });\n return { to: positionManager, data: params.calldata as Hex, value: BigInt(params.value) };\n } catch (cause) {\n if (cause instanceof UniswapSdkError) throw cause;\n throw new UniswapSdkError('INVALID_ARGUMENT', 'Official Uniswap SDK rejected the mint parameters', { cause });\n }\n}\n"]}
1
+ {"version":3,"file":"v4-transactions.js","sourceRoot":"","sources":["../src/v4-transactions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Currency } from '@uniswap/sdk-core';\nimport { decodeAbiParameters, decodeFunctionData, parseAbiParameters, zeroAddress, type Address, type Hex } from 'viem';\nimport { Percent, Pool, Position, V4PositionManager } from './official-sdk.cjs';\nimport { checkedAddress } from './pool.js';\nimport { invalid, UniswapSdkError } from './errors.js';\nimport { v4PositionManagerAbi } from './abis.js';\n\nexport type V4TransactionMaterial = { to: Address; data: Hex; value: bigint };\n\n/** Pool state as read from PoolManager/StateView (e.g. via `readV4Pool`), not yet a mint target. */\nexport type V4PoolState = {\n currency0: Currency;\n currency1: Currency;\n fee: number;\n tickSpacing: number;\n hooks: Address;\n sqrtPriceX96: bigint;\n liquidity: bigint;\n tickCurrent: number;\n};\n\nexport type V4MintPositionParams = {\n positionManager: Address;\n pool: V4PoolState;\n tickLower: number;\n tickUpper: number;\n /** Liquidity units to mint, not a token amount. */\n liquidity: bigint;\n recipient: Address;\n /** Integer basis points, 0-10000. */\n slippageToleranceBps: number;\n deadlineSeconds: bigint;\n /** Passed to the hook's callbacks verbatim; this SDK does not construct it. */\n hookData?: Hex;\n /** Atomically initializes the pool before minting. Requires `pool.sqrtPriceX96` to be the intended starting price. */\n createPool?: boolean;\n};\n\nfunction slippagePercent(bps: number): Percent {\n if (!Number.isInteger(bps) || bps < 0 || bps > 10_000) {\n invalid('slippageToleranceBps must be an integer between 0 and 10000');\n }\n return new Percent(bps, 10_000);\n}\n\n/**\n * Builds unsigned calldata for `PositionManager.modifyLiquidities` minting a new v4 position.\n * Delegates encoding to `@uniswap/v4-sdk`'s `V4PositionManager`/`V4PositionPlanner` (the same\n * Actions/multicall encoding Uniswap's own SDK uses) rather than hand-rolling it, since v4's\n * calldata is a sequence of packed actions, not a single ABI-encoded function call like v3's.\n *\n * No Permit2 support yet — callers must have already approved the position manager via a plain\n * ERC20 approval, or the built transaction will revert on-chain. Hook-permission gating (refusing\n * a pool whose hook implements more than the caller has modelled) is also the caller's\n * responsibility; this function only encodes what it is given.\n */\nexport function buildV4MintPositionTransaction(input: V4MintPositionParams): V4TransactionMaterial {\n if (input.liquidity <= 0n) invalid('Mint liquidity must be positive');\n if (!Number.isInteger(input.tickLower) || !Number.isInteger(input.tickUpper) || input.tickLower >= input.tickUpper) {\n invalid('tickLower must be an integer less than tickUpper');\n }\n if (input.createPool && input.pool.sqrtPriceX96 <= 0n) invalid('createPool requires a positive initial sqrtPriceX96');\n const positionManager = checkedAddress(input.positionManager);\n const recipient = checkedAddress(input.recipient);\n const slippageTolerance = slippagePercent(input.slippageToleranceBps);\n\n try {\n const pool = new Pool(\n input.pool.currency0,\n input.pool.currency1,\n input.pool.fee,\n input.pool.tickSpacing,\n checkedAddress(input.pool.hooks),\n input.pool.sqrtPriceX96.toString(),\n input.pool.liquidity.toString(),\n input.pool.tickCurrent,\n );\n const position = new Position({\n pool,\n liquidity: input.liquidity.toString(),\n tickLower: input.tickLower,\n tickUpper: input.tickUpper,\n });\n const params = V4PositionManager.addCallParameters(position, {\n recipient,\n createPool: input.createPool ?? false,\n ...(input.createPool ? { sqrtPriceX96: input.pool.sqrtPriceX96.toString() } : {}),\n useNative: pool.currency0.isNative ? pool.currency0 : undefined,\n slippageTolerance,\n hookData: input.hookData,\n deadline: input.deadlineSeconds.toString(),\n });\n return { to: positionManager, data: params.calldata as Hex, value: BigInt(params.value) };\n } catch (cause) {\n if (cause instanceof UniswapSdkError) throw cause;\n throw new UniswapSdkError('INVALID_ARGUMENT', 'Official Uniswap SDK rejected the mint parameters', { cause });\n }\n}\n\nconst MINT_POSITION_ACTION = 2;\nconst SETTLE_PAIR_ACTION = 13;\nconst SWEEP_ACTION = 20;\n/** PositionManager's `msgSender()` sentinel; the only address `SWEEP` may refund to. */\nconst MSG_SENDER: Address = '0x0000000000000000000000000000000000000001';\n\nconst unlockDataParams = parseAbiParameters('bytes actions, bytes[] params');\nconst poolKeyStruct = '(address currency0, address currency1, uint24 fee, int24 tickSpacing, address hooks)';\nconst mintPositionParams = parseAbiParameters(\n `${poolKeyStruct} poolKey, int24 tickLower, int24 tickUpper, uint256 liquidity, uint128 amount0Max, uint128 amount1Max, address owner, bytes hookData`,\n);\nconst settlePairParams = parseAbiParameters('address currency0, address currency1');\nconst sweepParams = parseAbiParameters('address currency, address to');\n\nexport type V4PoolKeyMaterial = { currency0: Address; currency1: Address; fee: number; tickSpacing: number; hooks: Address };\nexport type V4MintActionParams = {\n poolKey: V4PoolKeyMaterial;\n tickLower: number;\n tickUpper: number;\n liquidity: bigint;\n amount0Max: bigint;\n amount1Max: bigint;\n owner: Address;\n hookData: Hex;\n deadline: bigint;\n /** Present only if this mint atomically initializes the pool; the price it initializes at. */\n createdAtSqrtPriceX96?: bigint;\n};\n\nfunction same(a: string, b: string): boolean {\n return a.toLowerCase() === b.toLowerCase();\n}\n\nfunction mismatch(message: string): never {\n throw new UniswapSdkError('CALLDATA_MISMATCH', message);\n}\n\n/** `bytes actions` packs one uint8 opcode per action, two hex characters each. */\nfunction decodeActionIds(actions: Hex): number[] {\n const hex = actions.slice(2);\n if (hex.length % 2 !== 0) mismatch('Mint calldata has a malformed action byte string');\n const ids: number[] = [];\n for (let i = 0; i < hex.length; i += 2) ids.push(parseInt(hex.slice(i, i + 2), 16));\n return ids;\n}\n\nfunction samePoolKey(a: V4PoolKeyMaterial, b: V4PoolKeyMaterial): boolean {\n return same(a.currency0, b.currency0) && same(a.currency1, b.currency1)\n && a.fee === b.fee && a.tickSpacing === b.tickSpacing && same(a.hooks, b.hooks);\n}\n\nexport type V4ExpectedMint = V4PoolKeyMaterial & {\n recipient: Address;\n /**\n * Required if this mint might atomically create the pool; the only price that\n * mint may set. Checked only in that direction: supplying it does not require\n * the calldata to actually create the pool — a plain mint into an\n * already-initialized pool is unaffected either way, distinguishable from a\n * pool-creating mint by `createdAtSqrtPriceX96` being absent from the result.\n */\n sqrtPriceX96?: bigint;\n};\n\n/**\n * Decodes and verifies calldata built by `buildV4MintPositionTransaction`: a\n * `modifyLiquidities` call — optionally wrapped in a `multicall` alongside pool\n * initialization — encoding exactly a MINT_POSITION action, a SETTLE_PAIR, and,\n * for a native-currency0 mint, a trailing SWEEP. This is the only action shape\n * that function produces; any other sequence is calldata this decoder does not\n * recognise as its own and refuses, rather than guessing at its meaning.\n *\n * `expected` must name the full pool (including `hooks`), not just the token\n * pair — a mint into the same pair through a different, unreviewed hook is a\n * different pool with different economics, not a cosmetic difference.\n * `currency0`/`currency1` must already be in canonical (sorted) order, and a\n * native-currency pool's `currency0` must be the zero address, matching how\n * `V4PoolKey`/`Pool` represent it elsewhere in this SDK — this function does\n * not reorder or reinterpret them. Pass `sqrtPriceX96` when the mint might\n * atomically create the pool; omitting it fails closed rather than silently\n * accepting whatever starting price the calldata sets.\n */\nexport function reviewV4MintPositionCalldata(data: Hex, expected: V4ExpectedMint): V4MintActionParams {\n try {\n const decoded = decodeFunctionData({ abi: v4PositionManagerAbi, data });\n let unlockData: Hex;\n let deadline: bigint;\n let initialization: { key: V4PoolKeyMaterial; sqrtPriceX96: bigint } | undefined;\n if (decoded.functionName === 'multicall') {\n const calls = decoded.args[0].map(call => decodeFunctionData({ abi: v4PositionManagerAbi, data: call }));\n if (calls.length !== 2 || calls[0]!.functionName !== 'initializePool' || calls[1]!.functionName !== 'modifyLiquidities') {\n mismatch('Mint calldata multicall must contain only pool initialization followed by one mint');\n }\n initialization = { key: calls[0]!.args[0] as V4PoolKeyMaterial, sqrtPriceX96: calls[0]!.args[1] as bigint };\n [unlockData, deadline] = calls[1]!.args as [Hex, bigint];\n } else if (decoded.functionName === 'modifyLiquidities') {\n [unlockData, deadline] = decoded.args;\n } else {\n return mismatch('Mint calldata is not a position-manager modifyLiquidities call');\n }\n\n const [actionsBytes, actionParams] = decodeAbiParameters(unlockDataParams, unlockData) as [Hex, readonly Hex[]];\n const actionIds = decodeActionIds(actionsBytes);\n if (actionIds.length !== actionParams.length) mismatch('Mint calldata has a different number of actions and action parameters');\n if (actionIds.length < 2 || actionIds.length > 3) mismatch('Mint calldata does not have the action count a plain mint produces');\n\n if (actionIds[0] !== MINT_POSITION_ACTION) mismatch('Mint calldata must begin with a MINT_POSITION action');\n const [poolKey, tickLower, tickUpper, liquidity, amount0Max, amount1Max, owner, hookData] = decodeAbiParameters(\n mintPositionParams,\n actionParams[0]!,\n ) as [V4PoolKeyMaterial, number, number, bigint, bigint, bigint, Address, Hex];\n if (liquidity <= 0n) mismatch('Mint calldata mints non-positive liquidity');\n\n if (initialization && !samePoolKey(initialization.key, poolKey)) {\n mismatch('Mint pool initialization targets a different pool than the position mint');\n }\n\n if (actionIds[1] !== SETTLE_PAIR_ACTION) mismatch('MINT_POSITION must be followed by a SETTLE_PAIR');\n const [settleCurrency0, settleCurrency1] = decodeAbiParameters(settlePairParams, actionParams[1]!) as [Address, Address];\n if (!same(settleCurrency0, poolKey.currency0) || !same(settleCurrency1, poolKey.currency1)) {\n mismatch('SETTLE_PAIR settles a different pair than the minted position');\n }\n\n if (actionIds.length === 3) {\n if (actionIds[2] !== SWEEP_ACTION) mismatch('Mint calldata has an unreviewed action after SETTLE_PAIR');\n const [sweepCurrency, sweepTo] = decodeAbiParameters(sweepParams, actionParams[2]!) as [Address, Address];\n if (!same(sweepCurrency, zeroAddress) && !same(sweepCurrency, poolKey.currency0)) {\n mismatch('SWEEP refunds an unexpected currency');\n }\n if (!same(sweepTo, MSG_SENDER)) mismatch('SWEEP sends the refund to an unexpected recipient');\n }\n\n if (!samePoolKey(poolKey, expected)) mismatch('Mint calldata targets a different pool than expected');\n if (!same(owner, expected.recipient)) mismatch('Mint calldata sends the position NFT to a different recipient');\n\n if (initialization) {\n if (expected.sqrtPriceX96 === undefined) {\n mismatch('Mint calldata initializes the pool but no expected starting price was supplied to verify it');\n }\n if (initialization.sqrtPriceX96 !== expected.sqrtPriceX96) {\n mismatch('Mint calldata initializes the pool at a different starting price than expected');\n }\n }\n\n return {\n poolKey, tickLower, tickUpper, liquidity, amount0Max, amount1Max, owner, hookData, deadline,\n ...(initialization ? { createdAtSqrtPriceX96: initialization.sqrtPriceX96 } : {}),\n };\n } catch (error) {\n if (error instanceof UniswapSdkError) throw error;\n throw new UniswapSdkError('CALLDATA_MISMATCH', 'Mint calldata contains undecodable position-manager calls', { cause: error });\n }\n}\n"]}
package/dist/v4.d.ts CHANGED
@@ -7,6 +7,8 @@ export type { V4Tick, V4TickWindow } from './depth.js';
7
7
  export { decodeV4PoolInitialization } from './events.js';
8
8
  export { decodeV4HookPermissions, unmodelledV4HookPermissions } from './hooks.js';
9
9
  export type { V4HookPermissions } from './hooks.js';
10
- export { buildV4MintPositionTransaction } from './v4-transactions.js';
11
- export type { V4MintPositionParams, V4PoolState, V4TransactionMaterial } from './v4-transactions.js';
10
+ export { buildV4MintPositionTransaction, reviewV4MintPositionCalldata } from './v4-transactions.js';
11
+ export type { V4ExpectedMint, V4MintActionParams, V4MintPositionParams, V4PoolKeyMaterial, V4PoolState, V4TransactionMaterial } from './v4-transactions.js';
12
+ export { buildV4MintPermitBatchTypedData } from './permit2.js';
13
+ export type { V4PermitBatchDetailInput, V4PermitBatchTypedData } from './permit2.js';
12
14
  //# 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;AACzD,OAAO,EAAE,uBAAuB,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAClF,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AACtE,YAAY,EAAE,oBAAoB,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,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;AACpD,OAAO,EAAE,8BAA8B,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AACpG,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC5J,OAAO,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC;AAC/D,YAAY,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC"}
package/dist/v4.js CHANGED
@@ -3,5 +3,6 @@ export { readV4Pool, quoteV4ExactInput, quoteV4Batch, verifyV4DeploymentWiring }
3
3
  export { readV4TickWindow, ticksInWord } from './depth.js';
4
4
  export { decodeV4PoolInitialization } from './events.js';
5
5
  export { decodeV4HookPermissions, unmodelledV4HookPermissions } from './hooks.js';
6
- export { buildV4MintPositionTransaction } from './v4-transactions.js';
6
+ export { buildV4MintPositionTransaction, reviewV4MintPositionCalldata } from './v4-transactions.js';
7
+ export { buildV4MintPermitBatchTypedData } from './permit2.js';
7
8
  //# 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;AACzD,OAAO,EAAE,uBAAuB,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAElF,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,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';\nexport { buildV4MintPositionTransaction } from './v4-transactions.js';\nexport type { V4MintPositionParams, V4PoolState, V4TransactionMaterial } from './v4-transactions.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;AAElF,OAAO,EAAE,8BAA8B,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAEpG,OAAO,EAAE,+BAA+B,EAAE,MAAM,cAAc,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';\nexport { buildV4MintPositionTransaction, reviewV4MintPositionCalldata } from './v4-transactions.js';\nexport type { V4ExpectedMint, V4MintActionParams, V4MintPositionParams, V4PoolKeyMaterial, V4PoolState, V4TransactionMaterial } from './v4-transactions.js';\nexport { buildV4MintPermitBatchTypedData } from './permit2.js';\nexport type { V4PermitBatchDetailInput, V4PermitBatchTypedData } from './permit2.js';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reptilianhq/uniswap-sdk",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Deployment-explicit Uniswap observations and reviewed transaction material.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -68,6 +68,10 @@
68
68
  "types": "./dist/providers.d.ts",
69
69
  "import": "./dist/providers.js"
70
70
  },
71
+ "./permit2": {
72
+ "types": "./dist/permit2.d.ts",
73
+ "import": "./dist/permit2.js"
74
+ },
71
75
  "./provenance/mainnet.json": "./provenance/mainnet.json",
72
76
  "./provenance/testnet.json": "./provenance/testnet.json"
73
77
  },
@@ -88,8 +92,10 @@
88
92
  "prepack": "npm run build"
89
93
  },
90
94
  "dependencies": {
95
+ "@uniswap/permit2-sdk": "1.4.0",
91
96
  "@uniswap/sdk-core": "7.19.2",
92
- "@uniswap/v4-sdk": "2.3.3"
97
+ "@uniswap/v4-sdk": "2.3.3",
98
+ "tslib": "2.8.1"
93
99
  },
94
100
  "peerDependencies": {
95
101
  "viem": ">=2.55.0 <3"
@@ -119,6 +125,6 @@
119
125
  "reptilianRelease": {
120
126
  "schemaVersion": 1,
121
127
  "group": "uniswap-sdk",
122
- "sourceSha": "c050f60c50fa89a88acb7976429b4c08a18fdc84"
128
+ "sourceSha": "d35608758d0aaad7f72819147bc9dd39ad612a2c"
123
129
  }
124
130
  }