sablier 3.3.5 → 3.4.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.
Files changed (76) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/cjs/evm/helpers.js +11 -15
  3. package/dist/cjs/evm/helpers.js.map +1 -1
  4. package/dist/cjs/evm/releases/features.js +118 -0
  5. package/dist/cjs/evm/releases/features.js.map +1 -0
  6. package/dist/cjs/evm/releases/resolvers.js +3 -0
  7. package/dist/cjs/evm/releases/resolvers.js.map +1 -1
  8. package/dist/cjs/evm/types.js.map +1 -1
  9. package/dist/cjs/helpers.js +8 -2
  10. package/dist/cjs/helpers.js.map +1 -1
  11. package/dist/esm/evm/helpers.js +2 -15
  12. package/dist/esm/evm/helpers.js.map +1 -1
  13. package/dist/esm/evm/releases/features.js +105 -0
  14. package/dist/esm/evm/releases/features.js.map +1 -0
  15. package/dist/esm/evm/releases/resolvers.js +3 -0
  16. package/dist/esm/evm/releases/resolvers.js.map +1 -1
  17. package/dist/esm/evm/types.js.map +1 -1
  18. package/dist/esm/helpers.js +8 -2
  19. package/dist/esm/helpers.js.map +1 -1
  20. package/dist/types/evm/helpers.d.ts +2 -9
  21. package/dist/types/evm/helpers.d.ts.map +1 -1
  22. package/dist/types/evm/releases/airdrops/index.d.ts +14637 -14567
  23. package/dist/types/evm/releases/airdrops/index.d.ts.map +1 -1
  24. package/dist/types/evm/releases/airdrops/v1.1/index.d.ts +650 -636
  25. package/dist/types/evm/releases/airdrops/v1.1/index.d.ts.map +1 -1
  26. package/dist/types/evm/releases/airdrops/v1.2/index.d.ts +1313 -1299
  27. package/dist/types/evm/releases/airdrops/v1.2/index.d.ts.map +1 -1
  28. package/dist/types/evm/releases/airdrops/v1.3/index.d.ts +2855 -2841
  29. package/dist/types/evm/releases/airdrops/v1.3/index.d.ts.map +1 -1
  30. package/dist/types/evm/releases/airdrops/v2.0/index.d.ts +4190 -4176
  31. package/dist/types/evm/releases/airdrops/v2.0/index.d.ts.map +1 -1
  32. package/dist/types/evm/releases/airdrops/v3.0/index.d.ts +5564 -5550
  33. package/dist/types/evm/releases/airdrops/v3.0/index.d.ts.map +1 -1
  34. package/dist/types/evm/releases/bob/index.d.ts +2605 -2591
  35. package/dist/types/evm/releases/bob/index.d.ts.map +1 -1
  36. package/dist/types/evm/releases/bob/v1.0/index.d.ts +2605 -2591
  37. package/dist/types/evm/releases/bob/v1.0/index.d.ts.map +1 -1
  38. package/dist/types/evm/releases/features.d.ts +123 -0
  39. package/dist/types/evm/releases/features.d.ts.map +1 -0
  40. package/dist/types/evm/releases/flow/index.d.ts +7040 -6984
  41. package/dist/types/evm/releases/flow/index.d.ts.map +1 -1
  42. package/dist/types/evm/releases/flow/v1.0/index.d.ts +1781 -1767
  43. package/dist/types/evm/releases/flow/v1.0/index.d.ts.map +1 -1
  44. package/dist/types/evm/releases/flow/v1.1/index.d.ts +1813 -1799
  45. package/dist/types/evm/releases/flow/v1.1/index.d.ts.map +1 -1
  46. package/dist/types/evm/releases/flow/v2.0/index.d.ts +1717 -1703
  47. package/dist/types/evm/releases/flow/v2.0/index.d.ts.map +1 -1
  48. package/dist/types/evm/releases/flow/v3.0/index.d.ts +1701 -1687
  49. package/dist/types/evm/releases/flow/v3.0/index.d.ts.map +1 -1
  50. package/dist/types/evm/releases/legacy/index.d.ts +1508 -1480
  51. package/dist/types/evm/releases/legacy/index.d.ts.map +1 -1
  52. package/dist/types/evm/releases/legacy/v1.0/index.d.ts +1236 -1222
  53. package/dist/types/evm/releases/legacy/v1.0/index.d.ts.map +1 -1
  54. package/dist/types/evm/releases/legacy/v1.1/index.d.ts +261 -247
  55. package/dist/types/evm/releases/legacy/v1.1/index.d.ts.map +1 -1
  56. package/dist/types/evm/releases/lockup/index.d.ts +20544 -20460
  57. package/dist/types/evm/releases/lockup/index.d.ts.map +1 -1
  58. package/dist/types/evm/releases/lockup/v1.0/index.d.ts +3846 -3832
  59. package/dist/types/evm/releases/lockup/v1.0/index.d.ts.map +1 -1
  60. package/dist/types/evm/releases/lockup/v1.1/index.d.ts +3997 -3983
  61. package/dist/types/evm/releases/lockup/v1.1/index.d.ts.map +1 -1
  62. package/dist/types/evm/releases/lockup/v1.2/index.d.ts +5791 -5777
  63. package/dist/types/evm/releases/lockup/v1.2/index.d.ts.map +1 -1
  64. package/dist/types/evm/releases/lockup/v2.0/index.d.ts +2347 -2333
  65. package/dist/types/evm/releases/lockup/v2.0/index.d.ts.map +1 -1
  66. package/dist/types/evm/releases/lockup/v3.0/index.d.ts +2220 -2206
  67. package/dist/types/evm/releases/lockup/v3.0/index.d.ts.map +1 -1
  68. package/dist/types/evm/releases/lockup/v4.0/index.d.ts +2477 -2463
  69. package/dist/types/evm/releases/lockup/v4.0/index.d.ts.map +1 -1
  70. package/dist/types/evm/releases/resolvers.d.ts +13 -3
  71. package/dist/types/evm/releases/resolvers.d.ts.map +1 -1
  72. package/dist/types/evm/types.d.ts +20 -3
  73. package/dist/types/evm/types.d.ts.map +1 -1
  74. package/dist/types/helpers.d.ts +2 -0
  75. package/dist/types/helpers.d.ts.map +1 -1
  76. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -9,6 +9,7 @@ The format is based on [Common Changelog](https://common-changelog.org/).
9
9
  > Starting with v2.0.0, this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). In v1.x, it
10
10
  > did not always follow Semantic Versioning.
11
11
 
12
+ [3.4.0]: https://github.com/sablier-labs/sdk/releases/tag/v3.4.0
12
13
  [3.3.5]: https://github.com/sablier-labs/sdk/releases/tag/v3.3.5
13
14
  [3.3.4]: https://github.com/sablier-labs/sdk/releases/tag/v3.3.4
14
15
  [3.3.3]: https://github.com/sablier-labs/sdk/releases/tag/v3.3.3
@@ -39,6 +40,28 @@ The format is based on [Common Changelog](https://common-changelog.org/).
39
40
  [1.1.0]: https://github.com/sablier-labs/sdk/releases/tag/v1.1.0
40
41
  [1.0.0]: https://github.com/sablier-labs/sdk/releases/tag/v1.0.0
41
42
 
43
+ ## [3.4.0] - 2026-04-07
44
+
45
+ ### Added
46
+
47
+ - Add release feature registry with per-protocol capability matrices for Airdrops, Flow, and Lockup
48
+ ([#169](https://github.com/sablier-labs/sdk/pull/169))
49
+ - Add `features` field to all release objects, populated automatically by release resolvers
50
+ ([#169](https://github.com/sablier-labs/sdk/pull/169))
51
+ - Add protocol-specific feature accessors: `getAirdropsReleaseFeatures`, `getFlowReleaseFeatures`,
52
+ `getLockupReleaseFeatures` ([#169](https://github.com/sablier-labs/sdk/pull/169))
53
+ - Add feature query helpers: `hasClaimTo`, `hasSponsor`, `supportsLockupBatch`, `supportsLockupPrbProxy`,
54
+ `usesLockupSplit` ([#169](https://github.com/sablier-labs/sdk/pull/169))
55
+ - Add release object overload for `isReleasePayable` and `isEvmReleasePayable`
56
+ ([#169](https://github.com/sablier-labs/sdk/pull/169))
57
+
58
+ ### Changed
59
+
60
+ - Refactor `isEvmReleasePayable` to read from the feature registry instead of hard-coded version comparisons
61
+ ([#169](https://github.com/sablier-labs/sdk/pull/169))
62
+ - Deprecate two-argument `isEvmReleasePayable(protocol, version)` in favor of `isEvmReleasePayable(release)`
63
+ ([#169](https://github.com/sablier-labs/sdk/pull/169))
64
+
42
65
  ## [3.3.5] - 2026-03-25
43
66
 
44
67
  ### Fixed
@@ -1,30 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.usesLockupSplit = exports.supportsLockupPrbProxy = exports.supportsLockupBatch = exports.isEvmReleasePayable = exports.hasSponsor = exports.hasClaimTo = exports.getLockupReleaseFeatures = exports.getFlowReleaseFeatures = exports.getAirdropsReleaseFeatures = void 0;
3
4
  exports.getContractExplorerURL = getContractExplorerURL;
4
- exports.isEvmReleasePayable = isEvmReleasePayable;
5
5
  exports.resolveEvmStreamId = resolveEvmStreamId;
6
6
  exports.resolveEvmContractByAlias = resolveEvmContractByAlias;
7
7
  exports.truncateEvmAddress = truncateEvmAddress;
8
8
  const explorer_url_js_1 = require("../internal/utils/explorer-url.js");
9
9
  const alias_catalog_js_1 = require("./contracts/alias-catalog.js");
10
10
  const enums_js_1 = require("./enums.js");
11
+ var features_js_1 = require("./releases/features.js");
12
+ Object.defineProperty(exports, "getAirdropsReleaseFeatures", { enumerable: true, get: function () { return features_js_1.getAirdropsReleaseFeatures; } });
13
+ Object.defineProperty(exports, "getFlowReleaseFeatures", { enumerable: true, get: function () { return features_js_1.getFlowReleaseFeatures; } });
14
+ Object.defineProperty(exports, "getLockupReleaseFeatures", { enumerable: true, get: function () { return features_js_1.getLockupReleaseFeatures; } });
15
+ Object.defineProperty(exports, "hasClaimTo", { enumerable: true, get: function () { return features_js_1.hasClaimTo; } });
16
+ Object.defineProperty(exports, "hasSponsor", { enumerable: true, get: function () { return features_js_1.hasSponsor; } });
17
+ Object.defineProperty(exports, "isEvmReleasePayable", { enumerable: true, get: function () { return features_js_1.isEvmReleasePayable; } });
18
+ Object.defineProperty(exports, "supportsLockupBatch", { enumerable: true, get: function () { return features_js_1.supportsLockupBatch; } });
19
+ Object.defineProperty(exports, "supportsLockupPrbProxy", { enumerable: true, get: function () { return features_js_1.supportsLockupPrbProxy; } });
20
+ Object.defineProperty(exports, "usesLockupSplit", { enumerable: true, get: function () { return features_js_1.usesLockupSplit; } });
11
21
  function getContractExplorerURL(explorerURL, contractAddress) {
12
22
  return (0, explorer_url_js_1.getContractExplorerURL)(explorerURL, contractAddress);
13
23
  }
14
- const MIN_PAYABLE_VERSIONS = {
15
- airdrops: enums_js_1.Version.Airdrops.V1_3,
16
- flow: enums_js_1.Version.Flow.V1_1,
17
- lockup: enums_js_1.Version.Lockup.V2_0,
18
- };
19
- function isEvmReleasePayable(protocol, version) {
20
- const minVersion = MIN_PAYABLE_VERSIONS[protocol];
21
- const [vMajor, vMinor] = version.slice(1).split(".").map(Number);
22
- const [mMajor, mMinor] = minVersion.slice(1).split(".").map(Number);
23
- if (vMajor !== mMajor) {
24
- return vMajor > mMajor;
25
- }
26
- return vMinor >= mMinor;
27
- }
28
24
  function resolveEvmStreamId(opts) {
29
25
  const { alias, chainId, tokenId, protocol } = opts;
30
26
  const contract = resolveEvmContractByAlias({ alias, chainId, protocol });
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/evm/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import { getContractExplorerURL as getContractExplorerURLInternal } from \"@/src/internal/utils/explorer-url.js\";\nimport type { Sablier, TruncateAddressOptions } from \"@/src/types.js\";\nimport { getAliasCatalog } from \"./contracts/alias-catalog.js\";\nimport { Protocol, Version } from \"./enums.js\";\n\n/**\n * Get the explorer URL for a contract. Compatible with Etherscan, Blockscout, etc.\n * @param explorerURL - The base explorer URL, e.g. https://etherscan.io\n * @param contractAddress - The contract object\n * @returns The explorer URL for the contract, e.g. https://etherscan.io/address/0x123...\n */\nexport function getContractExplorerURL(explorerURL: string, contractAddress: Sablier.EVM.Address) {\n return getContractExplorerURLInternal(explorerURL, contractAddress);\n}\n\n/**\n * Minimum versions that charge ETH fees on withdraw/claim\n * @see https://github.com/sablier-labs/airdrops/blob/main/CHANGELOG.md\n * @see https://github.com/sablier-labs/flow/blob/main/CHANGELOG.md\n * @see https://github.com/sablier-labs/lockup/blob/main/CHANGELOG.md\n */\nconst MIN_PAYABLE_VERSIONS = {\n airdrops: Version.Airdrops.V1_3,\n flow: Version.Flow.V1_1,\n lockup: Version.Lockup.V2_0,\n} as const;\n\nexport type PayableEvmProtocol = keyof typeof MIN_PAYABLE_VERSIONS;\n\n/**\n * Check if an EVM protocol release charges ETH fees on withdraw/claim operations.\n *\n * Starting from specific versions, Sablier contracts charge a small ETH fee when\n * recipients withdraw or claim tokens from streams and airdrops.\n *\n * @param protocol - The protocol name (\"airdrops\", \"flow\", or \"lockup\")\n * @param version - The version to check\n * @returns true if the release charges fees\n * @see {@link https://docs.sablier.com/concepts/fees} for fee details\n * @example\n * isEvmReleasePayable(\"airdrops\", \"v1.2\") // false\n * isEvmReleasePayable(\"airdrops\", \"v1.3\") // true\n * isEvmReleasePayable(\"lockup\", \"v1.2\") // false\n * isEvmReleasePayable(\"lockup\", \"v2.0\") // true\n * isEvmReleasePayable(\"flow\", \"v1.0\") // false\n * isEvmReleasePayable(\"flow\", \"v1.1\") // true\n */\nexport function isEvmReleasePayable(\n protocol: PayableEvmProtocol,\n version: Sablier.EVM.Version\n): boolean {\n const minVersion = MIN_PAYABLE_VERSIONS[protocol];\n // Compare versions: return true if version >= minVersion\n const [vMajor, vMinor] = version.slice(1).split(\".\").map(Number);\n const [mMajor, mMinor] = minVersion.slice(1).split(\".\").map(Number);\n if (vMajor !== mMajor) {\n return vMajor > mMajor;\n }\n return vMinor >= mMinor;\n}\n\n/**\n * Constructs a stream/airdrop entity ID for EVM chains in the format used by Sablier indexers.\n * Format: `{contractAddress}-{chainId}-{tokenId}`\n *\n * The contract address is lowercased for normalization, as EVM addresses are case-insensitive.\n *\n * @param opts - Configuration object\n * @param opts.alias - Contract alias (e.g., \"LL2\", \"LK2\", \"FL2\")\n * @param opts.chainId - Chain ID where the contract is deployed\n * @param opts.tokenId - Stream/airdrop token ID\n * @param opts.protocol - Optional protocol to disambiguate aliases\n * @returns Stream ID in format \"0xabc...-1-123\"\n * @example\n * resolveEvmStreamId({ alias: \"LL2\", chainId: 1, tokenId: 123n })\n * // => \"0xabc...-1-123\"\n */\nexport function resolveEvmStreamId(opts: {\n alias: string;\n chainId: number;\n tokenId: bigint | string | number;\n protocol?: Sablier.EVM.Protocol;\n}): string {\n const { alias, chainId, tokenId, protocol } = opts;\n\n const contract = resolveEvmContractByAlias({ alias, chainId, protocol });\n return `${contract.address.toLowerCase()}-${chainId}-${tokenId}`;\n}\n\n/**\n * Resolves an EVM contract by its alias from the alias catalog.\n *\n * @param opts - Configuration object\n * @param opts.alias - Contract alias (e.g., \"LL2\", \"LK2\", \"FL2\")\n * @param opts.chainId - Chain ID where the contract is deployed\n * @param opts.protocol - Optional protocol to disambiguate aliases that exist in multiple protocols\n * @returns The resolved contract\n * @throws Error if alias is not found or is ambiguous without protocol specified\n * @example\n * resolveEvmContractByAlias({ alias: \"LL2\", chainId: 1 })\n * // => { address: \"0x...\", name: \"SablierLockupLinear\", ... }\n */\nexport function resolveEvmContractByAlias(opts: {\n alias: string;\n chainId: number;\n protocol?: Sablier.EVM.Protocol;\n}): Sablier.EVM.Contract {\n const { alias, chainId, protocol } = opts;\n const aliasCatalog = getAliasCatalog();\n\n if (protocol) {\n const contract = aliasCatalog[protocol]?.[chainId]?.[alias];\n if (!contract) {\n throw new Error(\n `Sablier SDK: Unknown EVM contract alias \"${alias}\" on chain ${chainId} for protocol \"${protocol}\"`\n );\n }\n return contract;\n }\n\n const protocols: Sablier.EVM.Protocol[] = [\n Protocol.Airdrops,\n Protocol.Bob,\n Protocol.Flow,\n Protocol.Legacy,\n Protocol.Lockup,\n ];\n\n const matches = protocols\n .map((p) => aliasCatalog[p]?.[chainId]?.[alias])\n .filter(Boolean) as Sablier.EVM.Contract[];\n\n if (matches.length === 0) {\n throw new Error(`Sablier SDK: Unknown EVM contract alias \"${alias}\" on chain ${chainId}`);\n }\n\n if (matches.length > 1) {\n throw new Error(\n `Sablier SDK: Ambiguous EVM contract alias \"${alias}\" on chain ${chainId}; specify protocol`\n );\n }\n\n return matches[0];\n}\n\n/**\n * Truncate an Ethereum address for display purposes.\n * @param address - The Ethereum address to truncate (0x-prefixed)\n * @param options - Truncation options with start/end character counts (default: 4 each, must be >= 1)\n * @returns Truncated address in format \"0xcafe...beef\" or original if too short\n * @example\n * truncateEvmAddress(\"0x1234567890abcdef1234567890abcdef12345678\") // \"0x1234...5678\"\n * truncateEvmAddress(\"0x1234567890abcdef1234567890abcdef12345678\", { start: 6, end: 6 }) // \"0x123456...345678\"\n * truncateEvmAddress(\"0x1234567890abcdef1234567890abcdef12345678\", { start: 2, end: 6 }) // \"0x12...345678\"\n * truncateEvmAddress(\"0x123\") // \"0x123\" (too short, returns original)\n */\nexport function truncateEvmAddress(\n address: Sablier.EVM.Address,\n options?: TruncateAddressOptions\n): string {\n if (!address) {\n return address;\n }\n\n const start = options?.start ?? 4;\n const end = options?.end ?? 4;\n const minLength = 2 + start + end;\n\n if (address.length <= minLength) {\n return address;\n }\n\n const prefix = address.slice(0, 2 + start);\n const suffix = end === 0 ? \"\" : address.slice(-end);\n\n return `${prefix}...${suffix}`;\n}\n"]}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/evm/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import { getContractExplorerURL as getContractExplorerURLInternal } from \"@/src/internal/utils/explorer-url.js\";\nimport type { Sablier, TruncateAddressOptions } from \"@/src/types.js\";\nimport { getAliasCatalog } from \"./contracts/alias-catalog.js\";\nimport { Protocol } from \"./enums.js\";\n\nexport type { PayableEvmProtocol } from \"./releases/features.js\";\nexport {\n getAirdropsReleaseFeatures,\n getFlowReleaseFeatures,\n getLockupReleaseFeatures,\n hasClaimTo,\n hasSponsor,\n isEvmReleasePayable,\n supportsLockupBatch,\n supportsLockupPrbProxy,\n usesLockupSplit,\n} from \"./releases/features.js\";\n\n/**\n * Get the explorer URL for a contract. Compatible with Etherscan, Blockscout, etc.\n * @param explorerURL - The base explorer URL, e.g. https://etherscan.io\n * @param contractAddress - The contract object\n * @returns The explorer URL for the contract, e.g. https://etherscan.io/address/0x123...\n */\nexport function getContractExplorerURL(explorerURL: string, contractAddress: Sablier.EVM.Address) {\n return getContractExplorerURLInternal(explorerURL, contractAddress);\n}\n\n/**\n * Constructs a stream/airdrop entity ID for EVM chains in the format used by Sablier indexers.\n * Format: `{contractAddress}-{chainId}-{tokenId}`\n *\n * The contract address is lowercased for normalization, as EVM addresses are case-insensitive.\n *\n * @param opts - Configuration object\n * @param opts.alias - Contract alias (e.g., \"LL2\", \"LK2\", \"FL2\")\n * @param opts.chainId - Chain ID where the contract is deployed\n * @param opts.tokenId - Stream/airdrop token ID\n * @param opts.protocol - Optional protocol to disambiguate aliases\n * @returns Stream ID in format \"0xabc...-1-123\"\n * @example\n * resolveEvmStreamId({ alias: \"LL2\", chainId: 1, tokenId: 123n })\n * // => \"0xabc...-1-123\"\n */\nexport function resolveEvmStreamId(opts: {\n alias: string;\n chainId: number;\n tokenId: bigint | string | number;\n protocol?: Sablier.EVM.Protocol;\n}): string {\n const { alias, chainId, tokenId, protocol } = opts;\n\n const contract = resolveEvmContractByAlias({ alias, chainId, protocol });\n return `${contract.address.toLowerCase()}-${chainId}-${tokenId}`;\n}\n\n/**\n * Resolves an EVM contract by its alias from the alias catalog.\n *\n * @param opts - Configuration object\n * @param opts.alias - Contract alias (e.g., \"LL2\", \"LK2\", \"FL2\")\n * @param opts.chainId - Chain ID where the contract is deployed\n * @param opts.protocol - Optional protocol to disambiguate aliases that exist in multiple protocols\n * @returns The resolved contract\n * @throws Error if alias is not found or is ambiguous without protocol specified\n * @example\n * resolveEvmContractByAlias({ alias: \"LL2\", chainId: 1 })\n * // => { address: \"0x...\", name: \"SablierLockupLinear\", ... }\n */\nexport function resolveEvmContractByAlias(opts: {\n alias: string;\n chainId: number;\n protocol?: Sablier.EVM.Protocol;\n}): Sablier.EVM.Contract {\n const { alias, chainId, protocol } = opts;\n const aliasCatalog = getAliasCatalog();\n\n if (protocol) {\n const contract = aliasCatalog[protocol]?.[chainId]?.[alias];\n if (!contract) {\n throw new Error(\n `Sablier SDK: Unknown EVM contract alias \"${alias}\" on chain ${chainId} for protocol \"${protocol}\"`\n );\n }\n return contract;\n }\n\n const protocols: Sablier.EVM.Protocol[] = [\n Protocol.Airdrops,\n Protocol.Bob,\n Protocol.Flow,\n Protocol.Legacy,\n Protocol.Lockup,\n ];\n\n const matches = protocols\n .map((p) => aliasCatalog[p]?.[chainId]?.[alias])\n .filter(Boolean) as Sablier.EVM.Contract[];\n\n if (matches.length === 0) {\n throw new Error(`Sablier SDK: Unknown EVM contract alias \"${alias}\" on chain ${chainId}`);\n }\n\n if (matches.length > 1) {\n throw new Error(\n `Sablier SDK: Ambiguous EVM contract alias \"${alias}\" on chain ${chainId}; specify protocol`\n );\n }\n\n return matches[0];\n}\n\n/**\n * Truncate an Ethereum address for display purposes.\n * @param address - The Ethereum address to truncate (0x-prefixed)\n * @param options - Truncation options with start/end character counts (default: 4 each, must be >= 1)\n * @returns Truncated address in format \"0xcafe...beef\" or original if too short\n * @example\n * truncateEvmAddress(\"0x1234567890abcdef1234567890abcdef12345678\") // \"0x1234...5678\"\n * truncateEvmAddress(\"0x1234567890abcdef1234567890abcdef12345678\", { start: 6, end: 6 }) // \"0x123456...345678\"\n * truncateEvmAddress(\"0x1234567890abcdef1234567890abcdef12345678\", { start: 2, end: 6 }) // \"0x12...345678\"\n * truncateEvmAddress(\"0x123\") // \"0x123\" (too short, returns original)\n */\nexport function truncateEvmAddress(\n address: Sablier.EVM.Address,\n options?: TruncateAddressOptions\n): string {\n if (!address) {\n return address;\n }\n\n const start = options?.start ?? 4;\n const end = options?.end ?? 4;\n const minLength = 2 + start + end;\n\n if (address.length <= minLength) {\n return address;\n }\n\n const prefix = address.slice(0, 2 + start);\n const suffix = end === 0 ? \"\" : address.slice(-end);\n\n return `${prefix}...${suffix}`;\n}\n"]}
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.evmReleaseFeatures = void 0;
4
+ exports.getEvmReleaseFeatures = getEvmReleaseFeatures;
5
+ exports.getAirdropsReleaseFeatures = getAirdropsReleaseFeatures;
6
+ exports.getFlowReleaseFeatures = getFlowReleaseFeatures;
7
+ exports.getLockupReleaseFeatures = getLockupReleaseFeatures;
8
+ exports.isEvmReleasePayable = isEvmReleasePayable;
9
+ exports.hasClaimTo = hasClaimTo;
10
+ exports.hasSponsor = hasSponsor;
11
+ exports.supportsLockupBatch = supportsLockupBatch;
12
+ exports.supportsLockupPrbProxy = supportsLockupPrbProxy;
13
+ exports.usesLockupSplit = usesLockupSplit;
14
+ const enums_js_1 = require("../../evm/enums.js");
15
+ function deepFreeze(value) {
16
+ if (typeof value !== "object" || value === null || Object.isFrozen(value)) {
17
+ return value;
18
+ }
19
+ for (const nestedValue of Object.values(value)) {
20
+ deepFreeze(nestedValue);
21
+ }
22
+ return Object.freeze(value);
23
+ }
24
+ const emptyReleaseFeatures = deepFreeze({});
25
+ exports.evmReleaseFeatures = deepFreeze({
26
+ [enums_js_1.Protocol.Airdrops]: {
27
+ [enums_js_1.Version.Airdrops.V1_1]: { claimTo: false, payable: false, sponsor: false },
28
+ [enums_js_1.Version.Airdrops.V1_2]: { claimTo: false, payable: false, sponsor: false },
29
+ [enums_js_1.Version.Airdrops.V1_3]: { claimTo: false, payable: true, sponsor: false },
30
+ [enums_js_1.Version.Airdrops.V2_0]: { claimTo: true, payable: true, sponsor: false },
31
+ [enums_js_1.Version.Airdrops.V3_0]: { claimTo: true, payable: true, sponsor: true },
32
+ },
33
+ [enums_js_1.Protocol.Bob]: {
34
+ [enums_js_1.Version.Bob.V1_0]: emptyReleaseFeatures,
35
+ },
36
+ [enums_js_1.Protocol.Flow]: {
37
+ [enums_js_1.Version.Flow.V1_0]: { payable: false },
38
+ [enums_js_1.Version.Flow.V1_1]: { payable: true },
39
+ [enums_js_1.Version.Flow.V2_0]: { payable: true },
40
+ [enums_js_1.Version.Flow.V3_0]: { payable: true },
41
+ },
42
+ [enums_js_1.Protocol.Legacy]: {
43
+ [enums_js_1.Version.Legacy.V1_0]: emptyReleaseFeatures,
44
+ [enums_js_1.Version.Legacy.V1_1]: emptyReleaseFeatures,
45
+ },
46
+ [enums_js_1.Protocol.Lockup]: {
47
+ [enums_js_1.Version.Lockup.V1_0]: { batch: false, legacyAbi: true, payable: false, prbProxy: true },
48
+ [enums_js_1.Version.Lockup.V1_1]: { batch: false, legacyAbi: true, payable: false, prbProxy: false },
49
+ [enums_js_1.Version.Lockup.V1_2]: { batch: false, legacyAbi: false, payable: false, prbProxy: false },
50
+ [enums_js_1.Version.Lockup.V2_0]: { batch: true, legacyAbi: false, payable: true, prbProxy: false },
51
+ [enums_js_1.Version.Lockup.V3_0]: { batch: true, legacyAbi: false, payable: true, prbProxy: false },
52
+ [enums_js_1.Version.Lockup.V4_0]: { batch: true, legacyAbi: false, payable: true, prbProxy: false },
53
+ },
54
+ });
55
+ const evmReleaseFeatureRegistry = exports.evmReleaseFeatures;
56
+ const payableReleaseFeatureRegistry = deepFreeze({
57
+ [enums_js_1.Protocol.Airdrops]: exports.evmReleaseFeatures[enums_js_1.Protocol.Airdrops],
58
+ [enums_js_1.Protocol.Flow]: exports.evmReleaseFeatures[enums_js_1.Protocol.Flow],
59
+ [enums_js_1.Protocol.Lockup]: exports.evmReleaseFeatures[enums_js_1.Protocol.Lockup],
60
+ });
61
+ function isPayableEvmProtocol(protocol) {
62
+ return protocol in payableReleaseFeatureRegistry;
63
+ }
64
+ function isPayableEvmRelease(release) {
65
+ return isPayableEvmProtocol(release.protocol);
66
+ }
67
+ function normalizePayableReleaseInput(releaseOrProtocol, version) {
68
+ if (typeof releaseOrProtocol !== "string") {
69
+ return releaseOrProtocol;
70
+ }
71
+ if (!version) {
72
+ throw new Error('Sablier SDK: Missing "version" for isEvmReleasePayable(protocol, version)');
73
+ }
74
+ return { protocol: releaseOrProtocol, version };
75
+ }
76
+ function getEvmReleaseFeatures(protocol, version) {
77
+ return evmReleaseFeatureRegistry[protocol][version];
78
+ }
79
+ function getAirdropsReleaseFeatures(version) {
80
+ return getEvmReleaseFeatures(enums_js_1.Protocol.Airdrops, version);
81
+ }
82
+ function getFlowReleaseFeatures(version) {
83
+ return getEvmReleaseFeatures(enums_js_1.Protocol.Flow, version);
84
+ }
85
+ function getLockupReleaseFeatures(version) {
86
+ return getEvmReleaseFeatures(enums_js_1.Protocol.Lockup, version);
87
+ }
88
+ function isEvmReleasePayable(releaseOrProtocol, version) {
89
+ const release = normalizePayableReleaseInput(releaseOrProtocol, version);
90
+ if (!isPayableEvmRelease(release)) {
91
+ return false;
92
+ }
93
+ const protocolRegistry = payableReleaseFeatureRegistry[release.protocol];
94
+ if (!protocolRegistry) {
95
+ return false;
96
+ }
97
+ const releaseFeatures = protocolRegistry[release.version];
98
+ if (!releaseFeatures) {
99
+ return false;
100
+ }
101
+ return releaseFeatures.payable;
102
+ }
103
+ function hasClaimTo(version) {
104
+ return getAirdropsReleaseFeatures(version).claimTo;
105
+ }
106
+ function hasSponsor(version) {
107
+ return getAirdropsReleaseFeatures(version).sponsor;
108
+ }
109
+ function supportsLockupBatch(version) {
110
+ return getLockupReleaseFeatures(version).batch;
111
+ }
112
+ function supportsLockupPrbProxy(version) {
113
+ return getLockupReleaseFeatures(version).prbProxy;
114
+ }
115
+ function usesLockupSplit(version) {
116
+ return getLockupReleaseFeatures(version).legacyAbi;
117
+ }
118
+ //# sourceMappingURL=features.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features.js","sourceRoot":"","sources":["../../../../src/evm/releases/features.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @file Canonical capability registry for every shipped EVM release.\n *\n * Release builders attach these feature bags to exported release objects, and\n * helper functions read from the same registry so version-dependent behavior\n * stays defined in one place.\n */\nimport { Protocol, Version } from \"@/src/evm/enums.js\";\nimport type { Sablier } from \"@/src/types.js\";\n\n/* -------------------------------------------------------------------------- */\n/* TYPES */\n/* -------------------------------------------------------------------------- */\n\nexport type EvmReleaseVersionByProtocol = {\n airdrops: Sablier.EVM.Version.Airdrops;\n bob: Sablier.EVM.Version.Bob;\n flow: Sablier.EVM.Version.Flow;\n legacy: Sablier.EVM.Version.Legacy;\n lockup: Sablier.EVM.Version.Lockup;\n};\n\nexport type EvmReleaseFeatureSetByProtocol = {\n airdrops: Sablier.EVM.AirdropsReleaseFeatures;\n bob: Sablier.EVM.EmptyReleaseFeatures;\n flow: Sablier.EVM.FlowReleaseFeatures;\n legacy: Sablier.EVM.EmptyReleaseFeatures;\n lockup: Sablier.EVM.LockupReleaseFeatures;\n};\n\ntype EvmReleaseFeatureRegistry = {\n [TProtocol in keyof EvmReleaseVersionByProtocol]: Record<\n EvmReleaseVersionByProtocol[TProtocol],\n EvmReleaseFeatureSetByProtocol[TProtocol]\n >;\n};\n\nexport type ReleaseFeaturesForProtocol<TProtocol extends keyof EvmReleaseFeatureSetByProtocol> =\n EvmReleaseFeatureSetByProtocol[TProtocol];\n\ntype ProtocolFeatureSet<TProtocol extends keyof EvmReleaseFeatureSetByProtocol> =\n EvmReleaseFeatureSetByProtocol[TProtocol];\n\ntype ProtocolWithBooleanFeature<TFeature extends PropertyKey> = {\n [TProtocol in keyof EvmReleaseFeatureSetByProtocol]: ProtocolFeatureSet<TProtocol> extends Record<\n TFeature,\n boolean\n >\n ? TProtocol\n : never;\n}[keyof EvmReleaseFeatureSetByProtocol];\n\ntype EvmReleaseReference = Pick<Sablier.EVM.Release, \"protocol\" | \"version\">;\ntype PayableEvmReleaseReference = {\n [TProtocol in PayableEvmProtocol]: {\n protocol: TProtocol;\n version: EvmReleaseVersionByProtocol[TProtocol];\n };\n}[PayableEvmProtocol];\n\nfunction deepFreeze<T>(value: T): T {\n if (typeof value !== \"object\" || value === null || Object.isFrozen(value)) {\n return value;\n }\n\n for (const nestedValue of Object.values(value as Record<string, unknown>)) {\n deepFreeze(nestedValue);\n }\n\n return Object.freeze(value);\n}\n\nconst emptyReleaseFeatures = deepFreeze({} as const satisfies Sablier.EVM.EmptyReleaseFeatures);\n\n/**\n * Protocol/version feature matrix used by both release resolvers and public helpers.\n */\nexport const evmReleaseFeatures = deepFreeze({\n [Protocol.Airdrops]: {\n [Version.Airdrops.V1_1]: { claimTo: false, payable: false, sponsor: false },\n [Version.Airdrops.V1_2]: { claimTo: false, payable: false, sponsor: false },\n [Version.Airdrops.V1_3]: { claimTo: false, payable: true, sponsor: false },\n [Version.Airdrops.V2_0]: { claimTo: true, payable: true, sponsor: false },\n [Version.Airdrops.V3_0]: { claimTo: true, payable: true, sponsor: true },\n },\n [Protocol.Bob]: {\n [Version.Bob.V1_0]: emptyReleaseFeatures,\n },\n [Protocol.Flow]: {\n [Version.Flow.V1_0]: { payable: false },\n [Version.Flow.V1_1]: { payable: true },\n [Version.Flow.V2_0]: { payable: true },\n [Version.Flow.V3_0]: { payable: true },\n },\n [Protocol.Legacy]: {\n [Version.Legacy.V1_0]: emptyReleaseFeatures,\n [Version.Legacy.V1_1]: emptyReleaseFeatures,\n },\n [Protocol.Lockup]: {\n [Version.Lockup.V1_0]: { batch: false, legacyAbi: true, payable: false, prbProxy: true },\n [Version.Lockup.V1_1]: { batch: false, legacyAbi: true, payable: false, prbProxy: false },\n [Version.Lockup.V1_2]: { batch: false, legacyAbi: false, payable: false, prbProxy: false },\n [Version.Lockup.V2_0]: { batch: true, legacyAbi: false, payable: true, prbProxy: false },\n [Version.Lockup.V3_0]: { batch: true, legacyAbi: false, payable: true, prbProxy: false },\n [Version.Lockup.V4_0]: { batch: true, legacyAbi: false, payable: true, prbProxy: false },\n },\n} as const satisfies EvmReleaseFeatureRegistry);\n\nexport type PayableEvmProtocol = ProtocolWithBooleanFeature<\"payable\">;\n\n/* -------------------------------------------------------------------------- */\n/* PRIVATE HELPERS */\n/* -------------------------------------------------------------------------- */\n\nconst evmReleaseFeatureRegistry: EvmReleaseFeatureRegistry = evmReleaseFeatures;\n\ntype PayableReleaseFeatureRegistry = {\n [TProtocol in PayableEvmProtocol]: Record<\n EvmReleaseVersionByProtocol[TProtocol],\n Pick<ProtocolFeatureSet<TProtocol>, \"payable\">\n >;\n};\n\nconst payableReleaseFeatureRegistry = deepFreeze({\n [Protocol.Airdrops]: evmReleaseFeatures[Protocol.Airdrops],\n [Protocol.Flow]: evmReleaseFeatures[Protocol.Flow],\n [Protocol.Lockup]: evmReleaseFeatures[Protocol.Lockup],\n} satisfies PayableReleaseFeatureRegistry);\n\n/**\n * Narrows protocol checks for helpers that only apply to fee-charging releases.\n */\nfunction isPayableEvmProtocol(protocol: Sablier.EVM.Protocol): protocol is PayableEvmProtocol {\n return protocol in payableReleaseFeatureRegistry;\n}\n\n/**\n * Narrows a release descriptor to protocols whose feature bag includes a payable flag.\n */\nfunction isPayableEvmRelease(release: EvmReleaseReference): release is PayableEvmReleaseReference {\n return isPayableEvmProtocol(release.protocol);\n}\n\n/**\n * Normalizes the supported payable helper overloads to the canonical release shape.\n */\nfunction normalizePayableReleaseInput(\n releaseOrProtocol: EvmReleaseReference | Sablier.EVM.Protocol,\n version?: Sablier.EVM.Version\n): EvmReleaseReference {\n if (typeof releaseOrProtocol !== \"string\") {\n return releaseOrProtocol;\n }\n\n if (!version) {\n throw new Error('Sablier SDK: Missing \"version\" for isEvmReleasePayable(protocol, version)');\n }\n\n return { protocol: releaseOrProtocol, version };\n}\n\n/* -------------------------------------------------------------------------- */\n/* FEATURES */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Returns the protocol-specific feature bag for a single EVM release.\n */\nexport function getEvmReleaseFeatures<TProtocol extends keyof EvmReleaseFeatureSetByProtocol>(\n protocol: TProtocol,\n version: EvmReleaseVersionByProtocol[TProtocol]\n): ReleaseFeaturesForProtocol<TProtocol> {\n return evmReleaseFeatureRegistry[protocol][version] as ReleaseFeaturesForProtocol<TProtocol>;\n}\n\n/**\n * Reads the airdrops capability matrix for one released version.\n */\nexport function getAirdropsReleaseFeatures(\n version: Sablier.EVM.Version.Airdrops\n): Sablier.EVM.AirdropsReleaseFeatures {\n return getEvmReleaseFeatures(Protocol.Airdrops, version);\n}\n\n/**\n * Reads the flow capability matrix for one released version.\n */\nexport function getFlowReleaseFeatures(\n version: Sablier.EVM.Version.Flow\n): Sablier.EVM.FlowReleaseFeatures {\n return getEvmReleaseFeatures(Protocol.Flow, version);\n}\n\n/**\n * Reads the lockup capability matrix for one released version.\n */\nexport function getLockupReleaseFeatures(\n version: Sablier.EVM.Version.Lockup\n): Sablier.EVM.LockupReleaseFeatures {\n return getEvmReleaseFeatures(Protocol.Lockup, version);\n}\n\n/**\n * Returns whether a release charges native-token fees on claim or withdraw operations.\n */\nexport function isEvmReleasePayable(release: EvmReleaseReference): boolean;\n/**\n * @deprecated Pass a release object instead. This overload will be removed in the next major version (v4).\n */\nexport function isEvmReleasePayable(\n protocol: Sablier.EVM.Protocol,\n version: Sablier.EVM.Version\n): boolean;\nexport function isEvmReleasePayable(\n releaseOrProtocol: EvmReleaseReference | Sablier.EVM.Protocol,\n version?: Sablier.EVM.Version\n): boolean {\n const release = normalizePayableReleaseInput(releaseOrProtocol, version);\n\n if (!isPayableEvmRelease(release)) {\n return false;\n }\n\n const protocolRegistry = payableReleaseFeatureRegistry[release.protocol] as\n | Record<Sablier.EVM.Version, { payable: boolean }>\n | undefined;\n\n if (!protocolRegistry) {\n return false;\n }\n\n const releaseFeatures = protocolRegistry[release.version];\n\n if (!releaseFeatures) {\n return false;\n }\n\n return releaseFeatures.payable;\n}\n\n/**\n * Returns whether the airdrops release supports the `claimTo` function for claiming to a third-party address.\n */\nexport function hasClaimTo(version: Sablier.EVM.Version.Airdrops): boolean {\n return getAirdropsReleaseFeatures(version).claimTo;\n}\n\n/**\n * Returns whether the airdrops release supports sponsor-driven claims.\n */\nexport function hasSponsor(version: Sablier.EVM.Version.Airdrops): boolean {\n return getAirdropsReleaseFeatures(version).sponsor;\n}\n\n/**\n * Returns whether the lockup release exposes batch create or withdraw flows.\n */\nexport function supportsLockupBatch(version: Sablier.EVM.Version.Lockup): boolean {\n return getLockupReleaseFeatures(version).batch;\n}\n\n/**\n * Returns whether the lockup release integrates with PRBProxy.\n */\nexport function supportsLockupPrbProxy(version: Sablier.EVM.Version.Lockup): boolean {\n return getLockupReleaseFeatures(version).prbProxy;\n}\n\n/**\n * Returns whether the lockup release uses the split ABI layout.\n */\nexport function usesLockupSplit(version: Sablier.EVM.Version.Lockup): boolean {\n return getLockupReleaseFeatures(version).legacyAbi;\n}\n"]}
@@ -4,6 +4,7 @@ exports.resolvers = void 0;
4
4
  const queries_js_1 = require("../../evm/chains/queries.js");
5
5
  const resolver_js_1 = require("../../internal/factories/resolver.js");
6
6
  const nested_values_js_1 = require("../../internal/utils/nested-values.js");
7
+ const features_js_1 = require("./features.js");
7
8
  const contractMapper = (0, resolver_js_1.createContractMapper)(queries_js_1.chainsQueries);
8
9
  const standardDeploymentResolver = (0, resolver_js_1.createStandardDeploymentResolver)(contractMapper, "contracts");
9
10
  function createLockupV1Deployment(params) {
@@ -31,6 +32,7 @@ exports.resolvers = {
31
32
  return {
32
33
  ...params,
33
34
  contractNames: (0, nested_values_js_1.getNestedValues)(params.manifest),
35
+ features: (0, features_js_1.getEvmReleaseFeatures)(params.protocol, params.version),
34
36
  kind: "lockupV1",
35
37
  };
36
38
  },
@@ -38,6 +40,7 @@ exports.resolvers = {
38
40
  return {
39
41
  ...params,
40
42
  contractNames: (0, nested_values_js_1.getNestedValues)(params.manifest),
43
+ features: (0, features_js_1.getEvmReleaseFeatures)(params.protocol, params.version),
41
44
  kind: "standard",
42
45
  };
43
46
  },
@@ -1 +1 @@
1
- {"version":3,"file":"resolvers.js","sourceRoot":"","sources":["../../../../src/evm/releases/resolvers.ts"],"names":[],"mappings":";;;AAAA,4DAA4D;AAC5D,sEAG8C;AAC9C,4EAAwE;AAgCxE,MAAM,cAAc,GAAG,IAAA,kCAAoB,EAKzC,0BAAa,CAAC,CAAC;AAEjB,MAAM,0BAA0B,GAAG,IAAA,8CAAgC,EAMjE,cAAc,EAAE,WAAW,CAAC,CAAC;AAS/B,SAAS,wBAAwB,CAC/B,MAAgC;IAEhC,MAAM,EAAE,WAAW,EAAE,GAAG,UAAU,EAAE,GAAG,MAAM,CAAC;IAG9C,MAAM,eAAe,GAAG,EAAE,GAAG,WAAW,CAAC,IAAI,EAAE,GAAG,WAAW,CAAC,SAAS,EAAE,CAAC;IAC1E,MAAM,UAAU,GAAG,0BAA0B,CAAC;QAC5C,GAAG,UAAU;QACb,WAAW,EAAE,eAAe;KAC7B,CAAoC,CAAC;IAGtC,UAAU,CAAC,IAAI,GAAG,cAAc,CAAC,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC/D,UAAU,CAAC,SAAS,GAAG,cAAc,CAAC,WAAW,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAEzE,OAAO,UAAU,CAAC;AACpB,CAAC;AAMY,QAAA,SAAS,GAAG;IACvB,UAAU,EAAE;QAIV,QAAQ,EAAE,CAAC,MAAgC,EAAmC,EAAE;YAC9E,OAAO,wBAAwB,CAAC,MAAM,CAAC,CAAC;QAC1C,CAAC;QAKD,QAAQ,EAAE,CAAC,MAAgC,EAA0B,EAAE;YACrE,OAAO,0BAA0B,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;KACF;IAED,OAAO,EAAE;QAIP,QAAQ,EAAE,CACR,MAA4D,EACrB,EAAE;YACzC,OAAO;gBACL,GAAG,MAAM;gBACT,aAAa,EAAE,IAAA,kCAAe,EAAC,MAAM,CAAC,QAAQ,CAAC;gBAC/C,IAAI,EAAE,UAAU;aACjB,CAAC;QACJ,CAAC;QAKD,QAAQ,EAAE,CACR,MAA4D,EACrB,EAAE;YACzC,OAAO;gBACL,GAAG,MAAM;gBACT,aAAa,EAAE,IAAA,kCAAe,EAAC,MAAM,CAAC,QAAQ,CAAC;gBAC/C,IAAI,EAAE,UAAU;aACjB,CAAC;QACJ,CAAC;KACF;CACF,CAAC","sourcesContent":["import { chainsQueries } from \"@/src/evm/chains/queries.js\";\nimport {\n createContractMapper,\n createStandardDeploymentResolver,\n} from \"@/src/internal/factories/resolver.js\";\nimport { getNestedValues } from \"@/src/internal/utils/nested-values.js\";\nimport type { AliasMap } from \"@/src/shared/types.js\";\nimport type { Sablier } from \"@/src/types.js\";\n\n/* -------------------------------------------------------------------------- */\n/* TYPES */\n/* -------------------------------------------------------------------------- */\n\ntype DeploymentBaseParams = {\n protocol: Sablier.EVM.Protocol;\n version: Sablier.EVM.Version;\n chainId: number;\n aliasMap: AliasMap;\n};\n\ntype DeploymentLockupV1Params = DeploymentBaseParams & {\n contractMap: {\n core: Sablier.EVM.ContractMap;\n periphery: Sablier.EVM.ContractMap;\n };\n};\n\ntype DeploymentStandardParams = DeploymentBaseParams & {\n contractMap: Sablier.EVM.ContractMap;\n};\n\ntype ReleaseParams<T> = Omit<T, \"kind\" | \"contractNames\">;\n\n/* -------------------------------------------------------------------------- */\n/* PLATFORM SETUP */\n/* -------------------------------------------------------------------------- */\n\nconst contractMapper = createContractMapper<\n Sablier.EVM.Contract,\n Sablier.EVM.Protocol,\n Sablier.EVM.Version,\n Sablier.EVM.Address\n>(chainsQueries);\n\nconst standardDeploymentResolver = createStandardDeploymentResolver<\n Sablier.EVM.Deployment,\n Sablier.EVM.Contract,\n Sablier.EVM.Protocol,\n Sablier.EVM.Version,\n Sablier.EVM.Address\n>(contractMapper, \"contracts\");\n\n/* -------------------------------------------------------------------------- */\n/* EVM-SPECIFIC RESOLVERS */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Creates a LockupV1 deployment with separate core and periphery contracts\n */\nfunction createLockupV1Deployment(\n params: DeploymentLockupV1Params\n): Sablier.EVM.Deployment.LockupV1 {\n const { contractMap, ...baseParams } = params;\n\n // Create standard deployment with merged contracts\n const mergedContracts = { ...contractMap.core, ...contractMap.periphery };\n const deployment = standardDeploymentResolver({\n ...baseParams,\n contractMap: mergedContracts,\n }) as Sablier.EVM.Deployment.LockupV1;\n\n // Add separated core and periphery contracts\n deployment.core = contractMapper(contractMap.core, baseParams);\n deployment.periphery = contractMapper(contractMap.periphery, baseParams);\n\n return deployment;\n}\n\n/* -------------------------------------------------------------------------- */\n/* RESOLVERS */\n/* -------------------------------------------------------------------------- */\n\nexport const resolvers = {\n deployment: {\n /**\n * Creates a LockupV1 deployment with separate core and periphery contracts\n */\n lockupV1: (params: DeploymentLockupV1Params): Sablier.EVM.Deployment.LockupV1 => {\n return createLockupV1Deployment(params);\n },\n\n /**\n * Creates a standard deployment with all contracts in a single array\n */\n standard: (params: DeploymentStandardParams): Sablier.EVM.Deployment => {\n return standardDeploymentResolver(params);\n },\n },\n\n release: {\n /**\n * Creates a LockupV1 release with contract names extracted from manifest\n */\n lockupV1: <TAbiMap extends Sablier.EVM.AbiMap>(\n params: ReleaseParams<Sablier.EVM.Release.LockupV1<TAbiMap>>\n ): Sablier.EVM.Release.LockupV1<TAbiMap> => {\n return {\n ...params,\n contractNames: getNestedValues(params.manifest),\n kind: \"lockupV1\",\n };\n },\n\n /**\n * Creates a standard release with contract names extracted from manifest\n */\n standard: <TAbiMap extends Sablier.EVM.AbiMap>(\n params: ReleaseParams<Sablier.EVM.Release.Standard<TAbiMap>>\n ): Sablier.EVM.Release.Standard<TAbiMap> => {\n return {\n ...params,\n contractNames: getNestedValues(params.manifest),\n kind: \"standard\",\n };\n },\n },\n};\n"]}
1
+ {"version":3,"file":"resolvers.js","sourceRoot":"","sources":["../../../../src/evm/releases/resolvers.ts"],"names":[],"mappings":";;;AAAA,4DAA4D;AAC5D,sEAG8C;AAC9C,4EAAwE;AAIxE,+CAAsD;AA0CtD,MAAM,cAAc,GAAG,IAAA,kCAAoB,EAKzC,0BAAa,CAAC,CAAC;AAEjB,MAAM,0BAA0B,GAAG,IAAA,8CAAgC,EAMjE,cAAc,EAAE,WAAW,CAAC,CAAC;AAS/B,SAAS,wBAAwB,CAC/B,MAAgC;IAEhC,MAAM,EAAE,WAAW,EAAE,GAAG,UAAU,EAAE,GAAG,MAAM,CAAC;IAG9C,MAAM,eAAe,GAAG,EAAE,GAAG,WAAW,CAAC,IAAI,EAAE,GAAG,WAAW,CAAC,SAAS,EAAE,CAAC;IAC1E,MAAM,UAAU,GAAG,0BAA0B,CAAC;QAC5C,GAAG,UAAU;QACb,WAAW,EAAE,eAAe;KAC7B,CAAoC,CAAC;IAGtC,UAAU,CAAC,IAAI,GAAG,cAAc,CAAC,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC/D,UAAU,CAAC,SAAS,GAAG,cAAc,CAAC,WAAW,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAEzE,OAAO,UAAU,CAAC;AACpB,CAAC;AAMY,QAAA,SAAS,GAAG;IACvB,UAAU,EAAE;QAIV,QAAQ,EAAE,CAAC,MAAgC,EAAmC,EAAE;YAC9E,OAAO,wBAAwB,CAAC,MAAM,CAAC,CAAC;QAC1C,CAAC;QAKD,QAAQ,EAAE,CAAC,MAAgC,EAA0B,EAAE;YACrE,OAAO,0BAA0B,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;KACF;IAED,OAAO,EAAE;QAIP,QAAQ,EAAE,CAIR,MAGC,EACyB,EAAE;YAC5B,OAAO;gBACL,GAAG,MAAM;gBACT,aAAa,EAAE,IAAA,kCAAe,EAAC,MAAM,CAAC,QAAQ,CAAC;gBAC/C,QAAQ,EAAE,IAAA,mCAAqB,EAAiB,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC;gBAChF,IAAI,EAAE,UAAU;aACjB,CAAC;QACJ,CAAC;QAKD,QAAQ,EAAE,CAKR,MAGC,EACoC,EAAE;YACvC,OAAO;gBACL,GAAG,MAAM;gBACT,aAAa,EAAE,IAAA,kCAAe,EAAC,MAAM,CAAC,QAAQ,CAAC;gBAC/C,QAAQ,EAAE,IAAA,mCAAqB,EAAY,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC;gBAC3E,IAAI,EAAE,UAAU;aACjB,CAAC;QACJ,CAAC;KACF;CACF,CAAC","sourcesContent":["import { chainsQueries } from \"@/src/evm/chains/queries.js\";\nimport {\n createContractMapper,\n createStandardDeploymentResolver,\n} from \"@/src/internal/factories/resolver.js\";\nimport { getNestedValues } from \"@/src/internal/utils/nested-values.js\";\nimport type { AliasMap } from \"@/src/shared/types.js\";\nimport type { Sablier } from \"@/src/types.js\";\nimport type { EvmReleaseVersionByProtocol, ReleaseFeaturesForProtocol } from \"./features.js\";\nimport { getEvmReleaseFeatures } from \"./features.js\";\n\n/* -------------------------------------------------------------------------- */\n/* TYPES */\n/* -------------------------------------------------------------------------- */\n\ntype DeploymentBaseParams = {\n protocol: Sablier.EVM.Protocol;\n version: Sablier.EVM.Version;\n chainId: number;\n aliasMap: AliasMap;\n};\n\ntype DeploymentLockupV1Params = DeploymentBaseParams & {\n contractMap: {\n core: Sablier.EVM.ContractMap;\n periphery: Sablier.EVM.ContractMap;\n };\n};\n\ntype DeploymentStandardParams = DeploymentBaseParams & {\n contractMap: Sablier.EVM.ContractMap;\n};\n\ntype ReleaseParams<T> = Omit<T, \"kind\" | \"contractNames\" | \"features\" | \"protocol\" | \"version\">;\n\ntype StandardRelease<\n TProtocol extends keyof EvmReleaseVersionByProtocol,\n TAbiMap extends Sablier.EVM.AbiMap,\n> = Sablier.EVM.Release.Standard<TAbiMap, ReleaseFeaturesForProtocol<TProtocol>>;\n\ntype LockupProtocol = Extract<keyof EvmReleaseVersionByProtocol, \"lockup\">;\n\ntype LockupV1Release<TAbiMap extends Sablier.EVM.AbiMap> = Sablier.EVM.Release.LockupV1<\n TAbiMap,\n ReleaseFeaturesForProtocol<LockupProtocol>\n>;\n\n/* -------------------------------------------------------------------------- */\n/* PLATFORM SETUP */\n/* -------------------------------------------------------------------------- */\n\nconst contractMapper = createContractMapper<\n Sablier.EVM.Contract,\n Sablier.EVM.Protocol,\n Sablier.EVM.Version,\n Sablier.EVM.Address\n>(chainsQueries);\n\nconst standardDeploymentResolver = createStandardDeploymentResolver<\n Sablier.EVM.Deployment,\n Sablier.EVM.Contract,\n Sablier.EVM.Protocol,\n Sablier.EVM.Version,\n Sablier.EVM.Address\n>(contractMapper, \"contracts\");\n\n/* -------------------------------------------------------------------------- */\n/* EVM-SPECIFIC RESOLVERS */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Creates a LockupV1 deployment with separate core and periphery contracts\n */\nfunction createLockupV1Deployment(\n params: DeploymentLockupV1Params\n): Sablier.EVM.Deployment.LockupV1 {\n const { contractMap, ...baseParams } = params;\n\n // Create standard deployment with merged contracts\n const mergedContracts = { ...contractMap.core, ...contractMap.periphery };\n const deployment = standardDeploymentResolver({\n ...baseParams,\n contractMap: mergedContracts,\n }) as Sablier.EVM.Deployment.LockupV1;\n\n // Add separated core and periphery contracts\n deployment.core = contractMapper(contractMap.core, baseParams);\n deployment.periphery = contractMapper(contractMap.periphery, baseParams);\n\n return deployment;\n}\n\n/* -------------------------------------------------------------------------- */\n/* RESOLVERS */\n/* -------------------------------------------------------------------------- */\n\nexport const resolvers = {\n deployment: {\n /**\n * Creates a LockupV1 deployment with separate core and periphery contracts\n */\n lockupV1: (params: DeploymentLockupV1Params): Sablier.EVM.Deployment.LockupV1 => {\n return createLockupV1Deployment(params);\n },\n\n /**\n * Creates a standard deployment with all contracts in a single array\n */\n standard: (params: DeploymentStandardParams): Sablier.EVM.Deployment => {\n return standardDeploymentResolver(params);\n },\n },\n\n release: {\n /**\n * Creates a LockupV1 release with contract names extracted from manifest\n */\n lockupV1: <\n TAbiMap extends Sablier.EVM.AbiMap,\n TVersion extends EvmReleaseVersionByProtocol[LockupProtocol],\n >(\n params: ReleaseParams<LockupV1Release<TAbiMap>> & {\n protocol: LockupProtocol;\n version: TVersion;\n }\n ): LockupV1Release<TAbiMap> => {\n return {\n ...params,\n contractNames: getNestedValues(params.manifest),\n features: getEvmReleaseFeatures<LockupProtocol>(params.protocol, params.version),\n kind: \"lockupV1\",\n };\n },\n\n /**\n * Creates a standard release with contract names extracted from manifest\n */\n standard: <\n TProtocol extends keyof EvmReleaseVersionByProtocol,\n TAbiMap extends Sablier.EVM.AbiMap,\n TVersion extends EvmReleaseVersionByProtocol[TProtocol],\n >(\n params: ReleaseParams<StandardRelease<TProtocol, TAbiMap>> & {\n protocol: TProtocol;\n version: TVersion;\n }\n ): StandardRelease<TProtocol, TAbiMap> => {\n return {\n ...params,\n contractNames: getNestedValues(params.manifest),\n features: getEvmReleaseFeatures<TProtocol>(params.protocol, params.version),\n kind: \"standard\",\n };\n },\n },\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/evm/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AliasMap, Repository, Shared } from \"@/src/shared/types.js\";\nimport type * as enums from \"./enums.js\";\n\nexport namespace EVM {\n /** Ethereum address in the format 0x followed by 40 hex characters. */\n export type Address = `0x${string}`;\n\n export type AbiMap = { [contractName: string]: readonly object[] };\n export type Chain = Shared.Chain & {\n /** Whether this is a zkEVM like zkSync. */\n isZK: boolean;\n rpc: Shared.Chain[\"rpc\"] & {\n /** Alchemy RPC URL generator. */\n alchemy?: (apiKey: string) => string;\n /** Infura RPC URL generator. */\n infura?: (apiKey: string) => string;\n /** RouteMesh RPC URL generator. */\n routemesh?: (apiKey: string) => string;\n };\n };\n\n /**\n * The base contract type for EVM chains.\n */\n export type Contract = Shared.Contract<Address, Protocol, Version>;\n\n /**\n * Reverse mapping of contracts so that we can look up contracts by address.\n */\n export type ContractCatalog = {\n [protocol in Protocol]: {\n [chainId: number]: {\n [address: Address]: Contract;\n };\n };\n };\n\n /**\n * Reverse mapping of contracts by alias for O(1) lookup.\n */\n export type AliasCatalog = {\n [protocol in Protocol]: {\n [chainId: number]: {\n [alias: string]: Contract;\n };\n };\n };\n\n /** @internal */\n export type ContractMap = Shared.ContractMap<Address>;\n\n export type Protocol = `${enums.Protocol}` | enums.Protocol;\n\n export type CompilerSettings = {\n /** The EVM version such as shanghai, paris, etc. */\n evmVersion: string;\n /** Whether the optimizer is enabled. */\n optimizer: boolean;\n /** The number of optimizer runs. */\n optimizerRuns: number;\n /** Optional salt used for CREATE2 deployment. None implies deployment using CREATE. */\n salt?: string;\n /** The solc version used. */\n solcVersion: `v${number}.${number}.${number}`;\n /** Whether the IR is used. */\n viaIR: boolean;\n /** Optional zk version used, only valid for zkEVM chains. */\n zkVersion?: `v${number}.${number}.${number}`;\n };\n\n /* -------------------------------------------------------------------------- */\n /* DEPLOYMENT */\n /* -------------------------------------------------------------------------- */\n\n export namespace Deployment {\n export type Standard = {\n chainId: number;\n contracts: Contract[];\n /** TODO: Compiler settings for the contract. Not implemented yet. */\n compilerSettings?: CompilerSettings;\n };\n\n export type LockupV1 = Standard & {\n core: Contract[];\n periphery: Contract[];\n };\n }\n\n export type Deployment = Deployment.Standard | Deployment.LockupV1;\n\n /* -------------------------------------------------------------------------- */\n /* MANIFEST */\n /* -------------------------------------------------------------------------- */\n\n /**\n * Contract names for a given protocol and version.\n * Note that this may contain both deployed contracts and abstract contracts that are not deployed.\n */\n export namespace Manifest {\n export type LockupV1 = {\n core: Standard;\n periphery: Standard;\n };\n\n export type Standard = Shared.Manifest;\n }\n\n export type Manifest = Manifest.LockupV1 | Manifest.Standard;\n\n /* -------------------------------------------------------------------------- */\n /* RELEASE */\n /* -------------------------------------------------------------------------- */\n\n /**\n * A collection of deployments for a given protocol and version.\n */\n export namespace Release {\n type Common<TAbiMap extends AbiMap = AbiMap> = {\n abi: TAbiMap;\n /** A map of contract names to their aliases, used in the Sablier Interface and the Graph. */\n aliases?: AliasMap;\n /** An array of contract names. */\n contractNames: string[];\n /** Whether this is the latest release for this protocol. */\n isLatest: boolean;\n /** The kind of release. */\n kind: \"standard\" | \"lockupV1\";\n /** The Sablier protocol released, e.g. `airdrops`. */\n protocol: Protocol;\n /** Repository information for the release. */\n repository?: Repository;\n /** The version of the release, e.g., `v1.3`. */\n version: Version;\n };\n\n /**\n * Lockup v1.x release used to separate Lockup contracts into core and periphery sub-categories.\n * @see https://github.com/sablier-labs/v2-periphery\n */\n export type LockupV1<TAbiMap extends AbiMap = AbiMap> = Common<TAbiMap> & {\n deployments: Deployment.LockupV1[];\n kind: \"lockupV1\";\n manifest: Manifest.LockupV1;\n };\n\n export type Standard<TAbiMap extends AbiMap = AbiMap> = Common<TAbiMap> & {\n deployments: Deployment.Standard[];\n kind: \"standard\";\n manifest: Manifest.Standard;\n };\n }\n\n export type Release = Release.Standard | Release.LockupV1;\n\n /* -------------------------------------------------------------------------- */\n /* VERSION */\n /* -------------------------------------------------------------------------- */\n\n export namespace Version {\n export type Airdrops = `${enums.Version.Airdrops}` | enums.Version.Airdrops;\n\n export type Bob = `${enums.Version.Bob}` | enums.Version.Bob;\n\n export type Flow = `${enums.Version.Flow}` | enums.Version.Flow;\n\n export type Legacy = `${enums.Version.Legacy}` | enums.Version.Legacy;\n\n export type Lockup = `${enums.Version.Lockup}` | enums.Version.Lockup;\n }\n export type Version =\n | Version.Airdrops\n | Version.Bob\n | Version.Flow\n | Version.Legacy\n | Version.Lockup;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/evm/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AliasMap, Repository, Shared } from \"@/src/shared/types.js\";\nimport type * as enums from \"./enums.js\";\n\nexport namespace EVM {\n /** Ethereum address in the format 0x followed by 40 hex characters. */\n export type Address = `0x${string}`;\n\n export type AbiMap = { [contractName: string]: readonly object[] };\n export type Chain = Shared.Chain & {\n /** Whether this is a zkEVM like zkSync. */\n isZK: boolean;\n rpc: Shared.Chain[\"rpc\"] & {\n /** Alchemy RPC URL generator. */\n alchemy?: (apiKey: string) => string;\n /** Infura RPC URL generator. */\n infura?: (apiKey: string) => string;\n /** RouteMesh RPC URL generator. */\n routemesh?: (apiKey: string) => string;\n };\n };\n\n /**\n * The base contract type for EVM chains.\n */\n export type Contract = Shared.Contract<Address, Protocol, Version>;\n\n /**\n * Reverse mapping of contracts so that we can look up contracts by address.\n */\n export type ContractCatalog = {\n [protocol in Protocol]: {\n [chainId: number]: {\n [address: Address]: Contract;\n };\n };\n };\n\n /**\n * Reverse mapping of contracts by alias for O(1) lookup.\n */\n export type AliasCatalog = {\n [protocol in Protocol]: {\n [chainId: number]: {\n [alias: string]: Contract;\n };\n };\n };\n\n /** @internal */\n export type ContractMap = Shared.ContractMap<Address>;\n\n export type Protocol = `${enums.Protocol}` | enums.Protocol;\n\n export type CompilerSettings = {\n /** The EVM version such as shanghai, paris, etc. */\n evmVersion: string;\n /** Whether the optimizer is enabled. */\n optimizer: boolean;\n /** The number of optimizer runs. */\n optimizerRuns: number;\n /** Optional salt used for CREATE2 deployment. None implies deployment using CREATE. */\n salt?: string;\n /** The solc version used. */\n solcVersion: `v${number}.${number}.${number}`;\n /** Whether the IR is used. */\n viaIR: boolean;\n /** Optional zk version used, only valid for zkEVM chains. */\n zkVersion?: `v${number}.${number}.${number}`;\n };\n\n /* -------------------------------------------------------------------------- */\n /* DEPLOYMENT */\n /* -------------------------------------------------------------------------- */\n\n export namespace Deployment {\n export type Standard = {\n chainId: number;\n contracts: Contract[];\n /** TODO: Compiler settings for the contract. Not implemented yet. */\n compilerSettings?: CompilerSettings;\n };\n\n export type LockupV1 = Standard & {\n core: Contract[];\n periphery: Contract[];\n };\n }\n\n export type Deployment = Deployment.Standard | Deployment.LockupV1;\n\n /* -------------------------------------------------------------------------- */\n /* MANIFEST */\n /* -------------------------------------------------------------------------- */\n\n /**\n * Contract names for a given protocol and version.\n * Note that this may contain both deployed contracts and abstract contracts that are not deployed.\n */\n export namespace Manifest {\n export type LockupV1 = {\n core: Standard;\n periphery: Standard;\n };\n\n export type Standard = Shared.Manifest;\n }\n\n export type Manifest = Manifest.LockupV1 | Manifest.Standard;\n\n /* -------------------------------------------------------------------------- */\n /* RELEASE */\n /* -------------------------------------------------------------------------- */\n\n export type AirdropsReleaseFeatures = {\n payable: boolean;\n claimTo: boolean;\n sponsor: boolean;\n };\n\n export type FlowReleaseFeatures = {\n payable: boolean;\n };\n\n export type LockupReleaseFeatures = {\n payable: boolean;\n prbProxy: boolean;\n batch: boolean;\n legacyAbi: boolean;\n };\n\n export type EmptyReleaseFeatures = Record<never, never>;\n\n export type EvmReleaseFeatures =\n | AirdropsReleaseFeatures\n | FlowReleaseFeatures\n | LockupReleaseFeatures\n | EmptyReleaseFeatures;\n\n /**\n * A collection of deployments for a given protocol and version.\n */\n export namespace Release {\n type Common<\n TAbiMap extends AbiMap = AbiMap,\n TFeatures extends EvmReleaseFeatures = EvmReleaseFeatures,\n > = {\n abi: TAbiMap;\n /** A map of contract names to their aliases, used in the Sablier Interface and the Graph. */\n aliases?: AliasMap;\n /** An array of contract names. */\n contractNames: string[];\n /** Release capabilities keyed to the owning protocol. */\n features: TFeatures;\n /** Whether this is the latest release for this protocol. */\n isLatest: boolean;\n /** The kind of release. */\n kind: \"standard\" | \"lockupV1\";\n /** The Sablier protocol released, e.g. `airdrops`. */\n protocol: Protocol;\n /** Repository information for the release. */\n repository?: Repository;\n /** The version of the release, e.g., `v1.3`. */\n version: Version;\n };\n\n /**\n * Lockup v1.x release used to separate Lockup contracts into core and periphery sub-categories.\n * @see https://github.com/sablier-labs/v2-periphery\n */\n export type LockupV1<\n TAbiMap extends AbiMap = AbiMap,\n TFeatures extends EvmReleaseFeatures = EvmReleaseFeatures,\n > = Common<TAbiMap, TFeatures> & {\n deployments: Deployment.LockupV1[];\n kind: \"lockupV1\";\n manifest: Manifest.LockupV1;\n };\n\n export type Standard<\n TAbiMap extends AbiMap = AbiMap,\n TFeatures extends EvmReleaseFeatures = EvmReleaseFeatures,\n > = Common<TAbiMap, TFeatures> & {\n deployments: Deployment.Standard[];\n kind: \"standard\";\n manifest: Manifest.Standard;\n };\n }\n\n export type Release = Release.Standard | Release.LockupV1;\n\n /* -------------------------------------------------------------------------- */\n /* VERSION */\n /* -------------------------------------------------------------------------- */\n\n export namespace Version {\n export type Airdrops = `${enums.Version.Airdrops}` | enums.Version.Airdrops;\n\n export type Bob = `${enums.Version.Bob}` | enums.Version.Bob;\n\n export type Flow = `${enums.Version.Flow}` | enums.Version.Flow;\n\n export type Legacy = `${enums.Version.Legacy}` | enums.Version.Legacy;\n\n export type Lockup = `${enums.Version.Lockup}` | enums.Version.Lockup;\n }\n export type Version =\n | Version.Airdrops\n | Version.Bob\n | Version.Flow\n | Version.Legacy\n | Version.Lockup;\n}\n"]}
@@ -42,8 +42,14 @@ function isVersionBefore(version, before) {
42
42
  function isVersionAfter(version, after) {
43
43
  return compareVersions(version, after) > 0;
44
44
  }
45
- function isReleasePayable(protocol, version) {
46
- return (0, helpers_js_1.isEvmReleasePayable)(protocol, version);
45
+ function isReleasePayable(releaseOrProtocol, version) {
46
+ if (typeof releaseOrProtocol !== "string") {
47
+ return (0, helpers_js_1.isEvmReleasePayable)(releaseOrProtocol);
48
+ }
49
+ if (!version) {
50
+ throw new Error('Sablier SDK: Missing "version" for isEvmReleasePayable(protocol, version)');
51
+ }
52
+ return (0, helpers_js_1.isEvmReleasePayable)(releaseOrProtocol, version);
47
53
  }
48
54
  function truncateAddress(address, options) {
49
55
  return address.startsWith("0x")
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA8BA,0CAQC;AAWD,0CAEC;AAWD,wCAEC;AAoBD,4CAKC;AAeD,0CAIC;AA6BD,0CA+BC;AAxKD,6CAAyD;AAEzD,iDAA+F;AAC/F,yDAA6D;AAC7D,oDAAmF;AAInF,mDAAiC;AACjC,sDAAoC;AASpC,MAAM,yBAAyB,GAAG,IAAI,GAAG,CAAC,CAAC,mBAAW,CAAC,QAAQ,EAAE,mBAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AAYtF,SAAgB,eAAe,CAAC,CAAU,EAAE,CAAU;IACpD,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAE3D,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IACD,OAAO,MAAM,GAAG,MAAM,CAAC;AACzB,CAAC;AAWD,SAAgB,eAAe,CAAC,OAAgB,EAAE,MAAe;IAC/D,OAAO,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;AAC9C,CAAC;AAWD,SAAgB,cAAc,CAAC,OAAgB,EAAE,KAAc;IAC7D,OAAO,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;AAC7C,CAAC;AAoBD,SAAgB,gBAAgB,CAC9B,QAA4B,EAC5B,OAA4B;IAE5B,OAAO,IAAA,gCAAmB,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC;AAeD,SAAgB,eAAe,CAAC,OAAe,EAAE,OAAgC;IAC/E,OAAO,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;QAC7B,CAAC,CAAC,IAAA,+BAAkB,EAAC,OAA8B,EAAE,OAAO,CAAC;QAC7D,CAAC,CAAC,IAAA,kCAAqB,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC;AAMY,QAAA,QAAQ,GAAG,eAAe,CAAC;AAuBxC,SAAgB,eAAe,CAAC,IAK/B;IACC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IACnD,MAAM,aAAa,GAAG,4BAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAGpD,IAAI,QAAQ,IAAI,aAAa,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,QAAuB,CAAC,EAAE,CAAC;QACzF,MAAM,IAAI,KAAK,CACb,0BAA0B,QAAQ,gDAAgD,OAAO,EAAE,CAC5F,CAAC;IACJ,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,IAAA,kCAAqB,EAAC;YAC3B,KAAK;YACL,OAAO;YACP,QAAQ,EAAE,QAAmC;YAC7C,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAA,+BAAkB,EAAC;QACxB,KAAK;QACL,OAAO;QACP,QAAQ,EAAE,QAAgC;QAC1C,OAAO;KACR,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { Protocol as EvmProtocol } from \"./evm/enums.js\";\nimport type { PayableEvmProtocol } from \"./evm/helpers.js\";\nimport { isEvmReleasePayable, resolveEvmStreamId, truncateEvmAddress } from \"./evm/helpers.js\";\nimport { SOLANA_CHAIN_IDS } from \"./solana/chains/chains.js\";\nimport { resolveSolanaStreamId, truncateSolanaAddress } from \"./solana/helpers.js\";\nimport type { Sablier, TruncateAddressOptions } from \"./types.js\";\n\n// Re-export platform-specific helpers\nexport * from \"./evm/helpers.js\";\nexport * from \"./solana/helpers.js\";\n\n// Re-export shared types\nexport type { TruncateAddressOptions } from \"./types.js\";\n\n/** Version type supporting both EVM and Solana protocols */\ntype Version = Sablier.EVM.Version | Sablier.Solana.Version;\n\n/** Protocols that exist on both EVM and Solana ecosystems */\nconst MULTI_ECOSYSTEM_PROTOCOLS = new Set([EvmProtocol.Airdrops, EvmProtocol.Lockup]);\n\n/**\n * Compare two semantic version strings.\n * @param a - First version string (e.g., \"v1.0\")\n * @param b - Second version string (e.g., \"v1.0\")\n * @returns -1 if a < b, 0 if a === b, 1 if a > b\n * @example\n * compareVersions(\"v1.0\", \"v2.0\") // -1\n * compareVersions(\"v2.0\", \"v1.0\") // 1\n * compareVersions(\"v1.1\", \"v1.1\") // 0\n */\nexport function compareVersions(a: Version, b: Version): number {\n const [aMajor, aMinor] = a.slice(1).split(\".\").map(Number);\n const [bMajor, bMinor] = b.slice(1).split(\".\").map(Number);\n\n if (aMajor !== bMajor) {\n return aMajor - bMajor;\n }\n return aMinor - bMinor;\n}\n\n/**\n * Check if a version comes before another chronologically.\n * @param version - The version to check\n * @param before - The reference version to compare against\n * @returns true if version comes before the reference version\n * @example\n * isVersionBefore(\"v1.0\", \"v2.0\") // true\n * isVersionBefore(\"v2.0\", \"v1.0\") // false\n */\nexport function isVersionBefore(version: Version, before: Version): boolean {\n return compareVersions(version, before) < 0;\n}\n\n/**\n * Check if a version comes after another chronologically.\n * @param version - The version to check\n * @param after - The reference version to compare against\n * @returns true if version comes after the reference version\n * @example\n * isVersionAfter(\"v2.0\", \"v1.0\") // true\n * isVersionAfter(\"v1.0\", \"v2.0\") // false\n */\nexport function isVersionAfter(version: Version, after: Version): boolean {\n return compareVersions(version, after) > 0;\n}\n\n/**\n * Check if a protocol release charges ETH fees on withdraw/claim operations.\n *\n * Starting from specific versions, Sablier contracts charge a small ETH fee when\n * recipients withdraw or claim tokens from streams and airdrops.\n *\n * @param protocol - The protocol name (\"airdrops\", \"flow\", or \"lockup\")\n * @param version - The version to check\n * @returns true if the release charges fees\n * @see {@link https://docs.sablier.com/concepts/fees} for fee details\n * @example\n * isReleasePayable(\"airdrops\", \"v1.2\") // false\n * isReleasePayable(\"airdrops\", \"v1.3\") // true\n * isReleasePayable(\"lockup\", \"v1.2\") // false\n * isReleasePayable(\"lockup\", \"v2.0\") // true\n * isReleasePayable(\"flow\", \"v1.0\") // false\n * isReleasePayable(\"flow\", \"v1.1\") // true\n */\nexport function isReleasePayable(\n protocol: PayableEvmProtocol,\n version: Sablier.EVM.Version\n): boolean {\n return isEvmReleasePayable(protocol, version);\n}\n\n/**\n * Truncate an Ethereum or Solana address for display purposes.\n * Automatically routes to the appropriate typed function based on address format.\n *\n * @param address - The address to truncate (Ethereum 0x-prefixed or Solana base58)\n * @param options - Optional truncation options with start and end character counts (default: 4 each)\n * @returns Truncated address in format \"0xcafe...beef\" or \"DYw8...NSKK\" or original if too short\n * @example\n * truncateAddress(\"0x1234567890abcdef1234567890abcdef12345678\") // \"0x1234...5678\"\n * truncateAddress(\"0x1234567890abcdef1234567890abcdef12345678\", { start: 6, end: 6 }) // \"0x123456...345678\"\n * truncateAddress(\"DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK\") // \"DYw8...NSKK\"\n * truncateAddress(\"0x123\") // \"0x123\" (too short, returns original)\n */\nexport function truncateAddress(address: string, options?: TruncateAddressOptions): string {\n return address.startsWith(\"0x\")\n ? truncateEvmAddress(address as Sablier.EVM.Address, options)\n : truncateSolanaAddress(address, options);\n}\n\n/**\n * Convenience alias for {@link truncateAddress}.\n * Also suitable for truncating arbitrary hex strings, not just addresses.\n */\nexport const truncate = truncateAddress;\n\n/**\n * Resolves a stream/airdrop entity ID for use with Sablier indexers.\n * Automatically routes to EVM or Solana based on chain ID.\n *\n * Format: `{contractAddress}-{chainId}-{tokenId}`\n *\n * @param opts - Configuration object\n * @param opts.alias - Contract/program alias (e.g., \"LL2\", \"LK2\", \"FL2\" for EVM; \"LL\" for Solana)\n * @param opts.chainId - Chain ID (EVM chains or Solana chains: 900000010, 900000020)\n * @param opts.tokenId - Stream/airdrop token ID\n * @param opts.protocol - Optional protocol to disambiguate aliases\n * @returns Stream ID in format \"0xabc...-1-123\" (EVM) or \"DYw8jC...-900000010-123\" (Solana)\n * @example\n * // EVM\n * resolveStreamId({ alias: \"LL2\", chainId: 1, tokenId: 123n })\n * // => \"0xabc...-1-123\"\n *\n * // Solana\n * resolveStreamId({ alias: \"LL\", chainId: 900000010, tokenId: 456n })\n * // => \"DYw8jC...-900000010-456\"\n */\nexport function resolveStreamId(opts: {\n alias: string;\n chainId: number;\n tokenId: bigint | string | number;\n protocol?: Sablier.EVM.Protocol | Sablier.Solana.Protocol;\n}): string {\n const { alias, chainId, tokenId, protocol } = opts;\n const isSolanaChain = SOLANA_CHAIN_IDS.has(chainId);\n\n // Validate protocol/chain compatibility\n if (protocol && isSolanaChain && !MULTI_ECOSYSTEM_PROTOCOLS.has(protocol as EvmProtocol)) {\n throw new Error(\n `Sablier SDK: Protocol \"${protocol}\" is EVM-only and not valid for Solana chain ${chainId}`\n );\n }\n\n if (isSolanaChain) {\n return resolveSolanaStreamId({\n alias,\n chainId,\n protocol: protocol as Sablier.Solana.Protocol,\n tokenId,\n });\n }\n\n return resolveEvmStreamId({\n alias,\n chainId,\n protocol: protocol as Sablier.EVM.Protocol,\n tokenId,\n });\n}\n"]}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA+BA,0CAQC;AAWD,0CAEC;AAWD,wCAEC;AAiCD,4CAaC;AAeD,0CAIC;AA6BD,0CA+BC;AA9LD,6CAAyD;AAEzD,iDAA+F;AAC/F,yDAA6D;AAC7D,oDAAmF;AAInF,mDAAiC;AACjC,sDAAoC;AAUpC,MAAM,yBAAyB,GAAG,IAAI,GAAG,CAAC,CAAC,mBAAW,CAAC,QAAQ,EAAE,mBAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AAYtF,SAAgB,eAAe,CAAC,CAAU,EAAE,CAAU;IACpD,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAE3D,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IACD,OAAO,MAAM,GAAG,MAAM,CAAC;AACzB,CAAC;AAWD,SAAgB,eAAe,CAAC,OAAgB,EAAE,MAAe;IAC/D,OAAO,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;AAC9C,CAAC;AAWD,SAAgB,cAAc,CAAC,OAAgB,EAAE,KAAc;IAC7D,OAAO,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;AAC7C,CAAC;AAiCD,SAAgB,gBAAgB,CAC9B,iBAA2D,EAC3D,OAA6B;IAE7B,IAAI,OAAO,iBAAiB,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,IAAA,gCAAmB,EAAC,iBAAiB,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IAC/F,CAAC;IAED,OAAO,IAAA,gCAAmB,EAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;AACzD,CAAC;AAeD,SAAgB,eAAe,CAAC,OAAe,EAAE,OAAgC;IAC/E,OAAO,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;QAC7B,CAAC,CAAC,IAAA,+BAAkB,EAAC,OAA8B,EAAE,OAAO,CAAC;QAC7D,CAAC,CAAC,IAAA,kCAAqB,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC;AAMY,QAAA,QAAQ,GAAG,eAAe,CAAC;AAuBxC,SAAgB,eAAe,CAAC,IAK/B;IACC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IACnD,MAAM,aAAa,GAAG,4BAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAGpD,IAAI,QAAQ,IAAI,aAAa,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,QAAuB,CAAC,EAAE,CAAC;QACzF,MAAM,IAAI,KAAK,CACb,0BAA0B,QAAQ,gDAAgD,OAAO,EAAE,CAC5F,CAAC;IACJ,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,IAAA,kCAAqB,EAAC;YAC3B,KAAK;YACL,OAAO;YACP,QAAQ,EAAE,QAAmC;YAC7C,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAA,+BAAkB,EAAC;QACxB,KAAK;QACL,OAAO;QACP,QAAQ,EAAE,QAAgC;QAC1C,OAAO;KACR,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { Protocol as EvmProtocol } from \"./evm/enums.js\";\nimport type { PayableEvmProtocol } from \"./evm/helpers.js\";\nimport { isEvmReleasePayable, resolveEvmStreamId, truncateEvmAddress } from \"./evm/helpers.js\";\nimport { SOLANA_CHAIN_IDS } from \"./solana/chains/chains.js\";\nimport { resolveSolanaStreamId, truncateSolanaAddress } from \"./solana/helpers.js\";\nimport type { Sablier, TruncateAddressOptions } from \"./types.js\";\n\n// Re-export platform-specific helpers\nexport * from \"./evm/helpers.js\";\nexport * from \"./solana/helpers.js\";\n\n// Re-export shared types\nexport type { TruncateAddressOptions } from \"./types.js\";\n\n/** Version type supporting both EVM and Solana protocols */\ntype Version = Sablier.EVM.Version | Sablier.Solana.Version;\ntype EvmReleaseReference = Pick<Sablier.EVM.Release, \"protocol\" | \"version\">;\n\n/** Protocols that exist on both EVM and Solana ecosystems */\nconst MULTI_ECOSYSTEM_PROTOCOLS = new Set([EvmProtocol.Airdrops, EvmProtocol.Lockup]);\n\n/**\n * Compare two semantic version strings.\n * @param a - First version string (e.g., \"v1.0\")\n * @param b - Second version string (e.g., \"v1.0\")\n * @returns -1 if a < b, 0 if a === b, 1 if a > b\n * @example\n * compareVersions(\"v1.0\", \"v2.0\") // -1\n * compareVersions(\"v2.0\", \"v1.0\") // 1\n * compareVersions(\"v1.1\", \"v1.1\") // 0\n */\nexport function compareVersions(a: Version, b: Version): number {\n const [aMajor, aMinor] = a.slice(1).split(\".\").map(Number);\n const [bMajor, bMinor] = b.slice(1).split(\".\").map(Number);\n\n if (aMajor !== bMajor) {\n return aMajor - bMajor;\n }\n return aMinor - bMinor;\n}\n\n/**\n * Check if a version comes before another chronologically.\n * @param version - The version to check\n * @param before - The reference version to compare against\n * @returns true if version comes before the reference version\n * @example\n * isVersionBefore(\"v1.0\", \"v2.0\") // true\n * isVersionBefore(\"v2.0\", \"v1.0\") // false\n */\nexport function isVersionBefore(version: Version, before: Version): boolean {\n return compareVersions(version, before) < 0;\n}\n\n/**\n * Check if a version comes after another chronologically.\n * @param version - The version to check\n * @param after - The reference version to compare against\n * @returns true if version comes after the reference version\n * @example\n * isVersionAfter(\"v2.0\", \"v1.0\") // true\n * isVersionAfter(\"v1.0\", \"v2.0\") // false\n */\nexport function isVersionAfter(version: Version, after: Version): boolean {\n return compareVersions(version, after) > 0;\n}\n\n/**\n * Check if a protocol release charges ETH fees on withdraw/claim operations.\n *\n * Starting from specific versions, Sablier contracts charge a small ETH fee when\n * recipients withdraw or claim tokens from streams and airdrops.\n *\n * @param release - The release object or `{ protocol, version }` pair to check\n * @returns true if the release charges fees\n * @see {@link https://docs.sablier.com/concepts/fees} for fee details\n * @example\n * isReleasePayable({ protocol: \"airdrops\", version: \"v1.2\" }) // false\n * isReleasePayable({ protocol: \"airdrops\", version: \"v1.3\" }) // true\n * isReleasePayable(\"airdrops\", \"v1.2\") // false\n * isReleasePayable(\"airdrops\", \"v1.3\") // true\n * isReleasePayable({ protocol: \"lockup\", version: \"v1.2\" }) // false\n * isReleasePayable({ protocol: \"lockup\", version: \"v2.0\" }) // true\n * isReleasePayable(\"lockup\", \"v1.2\") // false\n * isReleasePayable(\"lockup\", \"v2.0\") // true\n * isReleasePayable({ protocol: \"flow\", version: \"v1.0\" }) // false\n * isReleasePayable({ protocol: \"flow\", version: \"v1.1\" }) // true\n * isReleasePayable(\"flow\", \"v1.0\") // false\n * isReleasePayable(\"flow\", \"v1.1\") // true\n */\nexport function isReleasePayable(release: EvmReleaseReference): boolean;\n/**\n * @deprecated Pass a release object instead. This overload will be removed in the next major version (v4).\n */\nexport function isReleasePayable(\n protocol: PayableEvmProtocol,\n version: Sablier.EVM.Version\n): boolean;\nexport function isReleasePayable(\n releaseOrProtocol: EvmReleaseReference | PayableEvmProtocol,\n version?: Sablier.EVM.Version\n): boolean {\n if (typeof releaseOrProtocol !== \"string\") {\n return isEvmReleasePayable(releaseOrProtocol);\n }\n\n if (!version) {\n throw new Error('Sablier SDK: Missing \"version\" for isEvmReleasePayable(protocol, version)');\n }\n\n return isEvmReleasePayable(releaseOrProtocol, version);\n}\n\n/**\n * Truncate an Ethereum or Solana address for display purposes.\n * Automatically routes to the appropriate typed function based on address format.\n *\n * @param address - The address to truncate (Ethereum 0x-prefixed or Solana base58)\n * @param options - Optional truncation options with start and end character counts (default: 4 each)\n * @returns Truncated address in format \"0xcafe...beef\" or \"DYw8...NSKK\" or original if too short\n * @example\n * truncateAddress(\"0x1234567890abcdef1234567890abcdef12345678\") // \"0x1234...5678\"\n * truncateAddress(\"0x1234567890abcdef1234567890abcdef12345678\", { start: 6, end: 6 }) // \"0x123456...345678\"\n * truncateAddress(\"DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK\") // \"DYw8...NSKK\"\n * truncateAddress(\"0x123\") // \"0x123\" (too short, returns original)\n */\nexport function truncateAddress(address: string, options?: TruncateAddressOptions): string {\n return address.startsWith(\"0x\")\n ? truncateEvmAddress(address as Sablier.EVM.Address, options)\n : truncateSolanaAddress(address, options);\n}\n\n/**\n * Convenience alias for {@link truncateAddress}.\n * Also suitable for truncating arbitrary hex strings, not just addresses.\n */\nexport const truncate = truncateAddress;\n\n/**\n * Resolves a stream/airdrop entity ID for use with Sablier indexers.\n * Automatically routes to EVM or Solana based on chain ID.\n *\n * Format: `{contractAddress}-{chainId}-{tokenId}`\n *\n * @param opts - Configuration object\n * @param opts.alias - Contract/program alias (e.g., \"LL2\", \"LK2\", \"FL2\" for EVM; \"LL\" for Solana)\n * @param opts.chainId - Chain ID (EVM chains or Solana chains: 900000010, 900000020)\n * @param opts.tokenId - Stream/airdrop token ID\n * @param opts.protocol - Optional protocol to disambiguate aliases\n * @returns Stream ID in format \"0xabc...-1-123\" (EVM) or \"DYw8jC...-900000010-123\" (Solana)\n * @example\n * // EVM\n * resolveStreamId({ alias: \"LL2\", chainId: 1, tokenId: 123n })\n * // => \"0xabc...-1-123\"\n *\n * // Solana\n * resolveStreamId({ alias: \"LL\", chainId: 900000010, tokenId: 456n })\n * // => \"DYw8jC...-900000010-456\"\n */\nexport function resolveStreamId(opts: {\n alias: string;\n chainId: number;\n tokenId: bigint | string | number;\n protocol?: Sablier.EVM.Protocol | Sablier.Solana.Protocol;\n}): string {\n const { alias, chainId, tokenId, protocol } = opts;\n const isSolanaChain = SOLANA_CHAIN_IDS.has(chainId);\n\n // Validate protocol/chain compatibility\n if (protocol && isSolanaChain && !MULTI_ECOSYSTEM_PROTOCOLS.has(protocol as EvmProtocol)) {\n throw new Error(\n `Sablier SDK: Protocol \"${protocol}\" is EVM-only and not valid for Solana chain ${chainId}`\n );\n }\n\n if (isSolanaChain) {\n return resolveSolanaStreamId({\n alias,\n chainId,\n protocol: protocol as Sablier.Solana.Protocol,\n tokenId,\n });\n }\n\n return resolveEvmStreamId({\n alias,\n chainId,\n protocol: protocol as Sablier.EVM.Protocol,\n tokenId,\n });\n}\n"]}
@@ -1,23 +1,10 @@
1
1
  import { getContractExplorerURL as getContractExplorerURLInternal } from "../internal/utils/explorer-url.js";
2
2
  import { getAliasCatalog } from "./contracts/alias-catalog.js";
3
- import { Protocol, Version } from "./enums.js";
3
+ import { Protocol } from "./enums.js";
4
+ export { getAirdropsReleaseFeatures, getFlowReleaseFeatures, getLockupReleaseFeatures, hasClaimTo, hasSponsor, isEvmReleasePayable, supportsLockupBatch, supportsLockupPrbProxy, usesLockupSplit, } from "./releases/features.js";
4
5
  export function getContractExplorerURL(explorerURL, contractAddress) {
5
6
  return getContractExplorerURLInternal(explorerURL, contractAddress);
6
7
  }
7
- const MIN_PAYABLE_VERSIONS = {
8
- airdrops: Version.Airdrops.V1_3,
9
- flow: Version.Flow.V1_1,
10
- lockup: Version.Lockup.V2_0,
11
- };
12
- export function isEvmReleasePayable(protocol, version) {
13
- const minVersion = MIN_PAYABLE_VERSIONS[protocol];
14
- const [vMajor, vMinor] = version.slice(1).split(".").map(Number);
15
- const [mMajor, mMinor] = minVersion.slice(1).split(".").map(Number);
16
- if (vMajor !== mMajor) {
17
- return vMajor > mMajor;
18
- }
19
- return vMinor >= mMinor;
20
- }
21
8
  export function resolveEvmStreamId(opts) {
22
9
  const { alias, chainId, tokenId, protocol } = opts;
23
10
  const contract = resolveEvmContractByAlias({ alias, chainId, protocol });
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/evm/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import { getContractExplorerURL as getContractExplorerURLInternal } from \"@/src/internal/utils/explorer-url.js\";\nimport type { Sablier, TruncateAddressOptions } from \"@/src/types.js\";\nimport { getAliasCatalog } from \"./contracts/alias-catalog.js\";\nimport { Protocol, Version } from \"./enums.js\";\n\n/**\n * Get the explorer URL for a contract. Compatible with Etherscan, Blockscout, etc.\n * @param explorerURL - The base explorer URL, e.g. https://etherscan.io\n * @param contractAddress - The contract object\n * @returns The explorer URL for the contract, e.g. https://etherscan.io/address/0x123...\n */\nexport function getContractExplorerURL(explorerURL: string, contractAddress: Sablier.EVM.Address) {\n return getContractExplorerURLInternal(explorerURL, contractAddress);\n}\n\n/**\n * Minimum versions that charge ETH fees on withdraw/claim\n * @see https://github.com/sablier-labs/airdrops/blob/main/CHANGELOG.md\n * @see https://github.com/sablier-labs/flow/blob/main/CHANGELOG.md\n * @see https://github.com/sablier-labs/lockup/blob/main/CHANGELOG.md\n */\nconst MIN_PAYABLE_VERSIONS = {\n airdrops: Version.Airdrops.V1_3,\n flow: Version.Flow.V1_1,\n lockup: Version.Lockup.V2_0,\n} as const;\n\nexport type PayableEvmProtocol = keyof typeof MIN_PAYABLE_VERSIONS;\n\n/**\n * Check if an EVM protocol release charges ETH fees on withdraw/claim operations.\n *\n * Starting from specific versions, Sablier contracts charge a small ETH fee when\n * recipients withdraw or claim tokens from streams and airdrops.\n *\n * @param protocol - The protocol name (\"airdrops\", \"flow\", or \"lockup\")\n * @param version - The version to check\n * @returns true if the release charges fees\n * @see {@link https://docs.sablier.com/concepts/fees} for fee details\n * @example\n * isEvmReleasePayable(\"airdrops\", \"v1.2\") // false\n * isEvmReleasePayable(\"airdrops\", \"v1.3\") // true\n * isEvmReleasePayable(\"lockup\", \"v1.2\") // false\n * isEvmReleasePayable(\"lockup\", \"v2.0\") // true\n * isEvmReleasePayable(\"flow\", \"v1.0\") // false\n * isEvmReleasePayable(\"flow\", \"v1.1\") // true\n */\nexport function isEvmReleasePayable(\n protocol: PayableEvmProtocol,\n version: Sablier.EVM.Version\n): boolean {\n const minVersion = MIN_PAYABLE_VERSIONS[protocol];\n // Compare versions: return true if version >= minVersion\n const [vMajor, vMinor] = version.slice(1).split(\".\").map(Number);\n const [mMajor, mMinor] = minVersion.slice(1).split(\".\").map(Number);\n if (vMajor !== mMajor) {\n return vMajor > mMajor;\n }\n return vMinor >= mMinor;\n}\n\n/**\n * Constructs a stream/airdrop entity ID for EVM chains in the format used by Sablier indexers.\n * Format: `{contractAddress}-{chainId}-{tokenId}`\n *\n * The contract address is lowercased for normalization, as EVM addresses are case-insensitive.\n *\n * @param opts - Configuration object\n * @param opts.alias - Contract alias (e.g., \"LL2\", \"LK2\", \"FL2\")\n * @param opts.chainId - Chain ID where the contract is deployed\n * @param opts.tokenId - Stream/airdrop token ID\n * @param opts.protocol - Optional protocol to disambiguate aliases\n * @returns Stream ID in format \"0xabc...-1-123\"\n * @example\n * resolveEvmStreamId({ alias: \"LL2\", chainId: 1, tokenId: 123n })\n * // => \"0xabc...-1-123\"\n */\nexport function resolveEvmStreamId(opts: {\n alias: string;\n chainId: number;\n tokenId: bigint | string | number;\n protocol?: Sablier.EVM.Protocol;\n}): string {\n const { alias, chainId, tokenId, protocol } = opts;\n\n const contract = resolveEvmContractByAlias({ alias, chainId, protocol });\n return `${contract.address.toLowerCase()}-${chainId}-${tokenId}`;\n}\n\n/**\n * Resolves an EVM contract by its alias from the alias catalog.\n *\n * @param opts - Configuration object\n * @param opts.alias - Contract alias (e.g., \"LL2\", \"LK2\", \"FL2\")\n * @param opts.chainId - Chain ID where the contract is deployed\n * @param opts.protocol - Optional protocol to disambiguate aliases that exist in multiple protocols\n * @returns The resolved contract\n * @throws Error if alias is not found or is ambiguous without protocol specified\n * @example\n * resolveEvmContractByAlias({ alias: \"LL2\", chainId: 1 })\n * // => { address: \"0x...\", name: \"SablierLockupLinear\", ... }\n */\nexport function resolveEvmContractByAlias(opts: {\n alias: string;\n chainId: number;\n protocol?: Sablier.EVM.Protocol;\n}): Sablier.EVM.Contract {\n const { alias, chainId, protocol } = opts;\n const aliasCatalog = getAliasCatalog();\n\n if (protocol) {\n const contract = aliasCatalog[protocol]?.[chainId]?.[alias];\n if (!contract) {\n throw new Error(\n `Sablier SDK: Unknown EVM contract alias \"${alias}\" on chain ${chainId} for protocol \"${protocol}\"`\n );\n }\n return contract;\n }\n\n const protocols: Sablier.EVM.Protocol[] = [\n Protocol.Airdrops,\n Protocol.Bob,\n Protocol.Flow,\n Protocol.Legacy,\n Protocol.Lockup,\n ];\n\n const matches = protocols\n .map((p) => aliasCatalog[p]?.[chainId]?.[alias])\n .filter(Boolean) as Sablier.EVM.Contract[];\n\n if (matches.length === 0) {\n throw new Error(`Sablier SDK: Unknown EVM contract alias \"${alias}\" on chain ${chainId}`);\n }\n\n if (matches.length > 1) {\n throw new Error(\n `Sablier SDK: Ambiguous EVM contract alias \"${alias}\" on chain ${chainId}; specify protocol`\n );\n }\n\n return matches[0];\n}\n\n/**\n * Truncate an Ethereum address for display purposes.\n * @param address - The Ethereum address to truncate (0x-prefixed)\n * @param options - Truncation options with start/end character counts (default: 4 each, must be >= 1)\n * @returns Truncated address in format \"0xcafe...beef\" or original if too short\n * @example\n * truncateEvmAddress(\"0x1234567890abcdef1234567890abcdef12345678\") // \"0x1234...5678\"\n * truncateEvmAddress(\"0x1234567890abcdef1234567890abcdef12345678\", { start: 6, end: 6 }) // \"0x123456...345678\"\n * truncateEvmAddress(\"0x1234567890abcdef1234567890abcdef12345678\", { start: 2, end: 6 }) // \"0x12...345678\"\n * truncateEvmAddress(\"0x123\") // \"0x123\" (too short, returns original)\n */\nexport function truncateEvmAddress(\n address: Sablier.EVM.Address,\n options?: TruncateAddressOptions\n): string {\n if (!address) {\n return address;\n }\n\n const start = options?.start ?? 4;\n const end = options?.end ?? 4;\n const minLength = 2 + start + end;\n\n if (address.length <= minLength) {\n return address;\n }\n\n const prefix = address.slice(0, 2 + start);\n const suffix = end === 0 ? \"\" : address.slice(-end);\n\n return `${prefix}...${suffix}`;\n}\n"]}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/evm/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import { getContractExplorerURL as getContractExplorerURLInternal } from \"@/src/internal/utils/explorer-url.js\";\nimport type { Sablier, TruncateAddressOptions } from \"@/src/types.js\";\nimport { getAliasCatalog } from \"./contracts/alias-catalog.js\";\nimport { Protocol } from \"./enums.js\";\n\nexport type { PayableEvmProtocol } from \"./releases/features.js\";\nexport {\n getAirdropsReleaseFeatures,\n getFlowReleaseFeatures,\n getLockupReleaseFeatures,\n hasClaimTo,\n hasSponsor,\n isEvmReleasePayable,\n supportsLockupBatch,\n supportsLockupPrbProxy,\n usesLockupSplit,\n} from \"./releases/features.js\";\n\n/**\n * Get the explorer URL for a contract. Compatible with Etherscan, Blockscout, etc.\n * @param explorerURL - The base explorer URL, e.g. https://etherscan.io\n * @param contractAddress - The contract object\n * @returns The explorer URL for the contract, e.g. https://etherscan.io/address/0x123...\n */\nexport function getContractExplorerURL(explorerURL: string, contractAddress: Sablier.EVM.Address) {\n return getContractExplorerURLInternal(explorerURL, contractAddress);\n}\n\n/**\n * Constructs a stream/airdrop entity ID for EVM chains in the format used by Sablier indexers.\n * Format: `{contractAddress}-{chainId}-{tokenId}`\n *\n * The contract address is lowercased for normalization, as EVM addresses are case-insensitive.\n *\n * @param opts - Configuration object\n * @param opts.alias - Contract alias (e.g., \"LL2\", \"LK2\", \"FL2\")\n * @param opts.chainId - Chain ID where the contract is deployed\n * @param opts.tokenId - Stream/airdrop token ID\n * @param opts.protocol - Optional protocol to disambiguate aliases\n * @returns Stream ID in format \"0xabc...-1-123\"\n * @example\n * resolveEvmStreamId({ alias: \"LL2\", chainId: 1, tokenId: 123n })\n * // => \"0xabc...-1-123\"\n */\nexport function resolveEvmStreamId(opts: {\n alias: string;\n chainId: number;\n tokenId: bigint | string | number;\n protocol?: Sablier.EVM.Protocol;\n}): string {\n const { alias, chainId, tokenId, protocol } = opts;\n\n const contract = resolveEvmContractByAlias({ alias, chainId, protocol });\n return `${contract.address.toLowerCase()}-${chainId}-${tokenId}`;\n}\n\n/**\n * Resolves an EVM contract by its alias from the alias catalog.\n *\n * @param opts - Configuration object\n * @param opts.alias - Contract alias (e.g., \"LL2\", \"LK2\", \"FL2\")\n * @param opts.chainId - Chain ID where the contract is deployed\n * @param opts.protocol - Optional protocol to disambiguate aliases that exist in multiple protocols\n * @returns The resolved contract\n * @throws Error if alias is not found or is ambiguous without protocol specified\n * @example\n * resolveEvmContractByAlias({ alias: \"LL2\", chainId: 1 })\n * // => { address: \"0x...\", name: \"SablierLockupLinear\", ... }\n */\nexport function resolveEvmContractByAlias(opts: {\n alias: string;\n chainId: number;\n protocol?: Sablier.EVM.Protocol;\n}): Sablier.EVM.Contract {\n const { alias, chainId, protocol } = opts;\n const aliasCatalog = getAliasCatalog();\n\n if (protocol) {\n const contract = aliasCatalog[protocol]?.[chainId]?.[alias];\n if (!contract) {\n throw new Error(\n `Sablier SDK: Unknown EVM contract alias \"${alias}\" on chain ${chainId} for protocol \"${protocol}\"`\n );\n }\n return contract;\n }\n\n const protocols: Sablier.EVM.Protocol[] = [\n Protocol.Airdrops,\n Protocol.Bob,\n Protocol.Flow,\n Protocol.Legacy,\n Protocol.Lockup,\n ];\n\n const matches = protocols\n .map((p) => aliasCatalog[p]?.[chainId]?.[alias])\n .filter(Boolean) as Sablier.EVM.Contract[];\n\n if (matches.length === 0) {\n throw new Error(`Sablier SDK: Unknown EVM contract alias \"${alias}\" on chain ${chainId}`);\n }\n\n if (matches.length > 1) {\n throw new Error(\n `Sablier SDK: Ambiguous EVM contract alias \"${alias}\" on chain ${chainId}; specify protocol`\n );\n }\n\n return matches[0];\n}\n\n/**\n * Truncate an Ethereum address for display purposes.\n * @param address - The Ethereum address to truncate (0x-prefixed)\n * @param options - Truncation options with start/end character counts (default: 4 each, must be >= 1)\n * @returns Truncated address in format \"0xcafe...beef\" or original if too short\n * @example\n * truncateEvmAddress(\"0x1234567890abcdef1234567890abcdef12345678\") // \"0x1234...5678\"\n * truncateEvmAddress(\"0x1234567890abcdef1234567890abcdef12345678\", { start: 6, end: 6 }) // \"0x123456...345678\"\n * truncateEvmAddress(\"0x1234567890abcdef1234567890abcdef12345678\", { start: 2, end: 6 }) // \"0x12...345678\"\n * truncateEvmAddress(\"0x123\") // \"0x123\" (too short, returns original)\n */\nexport function truncateEvmAddress(\n address: Sablier.EVM.Address,\n options?: TruncateAddressOptions\n): string {\n if (!address) {\n return address;\n }\n\n const start = options?.start ?? 4;\n const end = options?.end ?? 4;\n const minLength = 2 + start + end;\n\n if (address.length <= minLength) {\n return address;\n }\n\n const prefix = address.slice(0, 2 + start);\n const suffix = end === 0 ? \"\" : address.slice(-end);\n\n return `${prefix}...${suffix}`;\n}\n"]}