@otim/utils 0.0.2-development.0 → 0.0.3

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 (36) hide show
  1. package/dist/api/index.js +11 -6
  2. package/dist/api/index.js.map +2 -2
  3. package/dist/api/index.mjs +11 -6
  4. package/dist/api/index.mjs.map +2 -2
  5. package/dist/api/schemas/payments.d.mts +3 -0
  6. package/dist/api/schemas/payments.d.ts +3 -0
  7. package/dist/api/schemas/payments.d.ts.map +1 -1
  8. package/dist/chains/config/all-chains.d.mts +4 -4
  9. package/dist/chains/config/all-chains.d.ts +4 -4
  10. package/dist/chains/config/all-chains.d.ts.map +1 -1
  11. package/dist/chains/index.js +8 -2
  12. package/dist/chains/index.js.map +2 -2
  13. package/dist/chains/index.mjs +8 -2
  14. package/dist/chains/index.mjs.map +2 -2
  15. package/dist/helpers/index.js +20 -0
  16. package/dist/helpers/index.js.map +2 -2
  17. package/dist/helpers/index.mjs +20 -0
  18. package/dist/helpers/index.mjs.map +2 -2
  19. package/dist/helpers/zod.d.mts +21 -0
  20. package/dist/helpers/zod.d.ts +21 -0
  21. package/dist/helpers/zod.d.ts.map +1 -1
  22. package/dist/payments/build.d.mts +1 -0
  23. package/dist/payments/build.d.ts +1 -0
  24. package/dist/payments/build.d.ts.map +1 -1
  25. package/dist/payments/comprehensive-payment-request.d.mts +1 -0
  26. package/dist/payments/comprehensive-payment-request.d.ts +1 -0
  27. package/dist/payments/comprehensive-payment-request.d.ts.map +1 -1
  28. package/dist/payments/index.js +16 -12
  29. package/dist/payments/index.js.map +2 -2
  30. package/dist/payments/index.mjs +16 -12
  31. package/dist/payments/index.mjs.map +2 -2
  32. package/dist/server/index.js +3 -3
  33. package/dist/server/index.js.map +1 -1
  34. package/dist/server/index.mjs +3 -3
  35. package/dist/server/index.mjs.map +1 -1
  36. package/package.json +2 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/payments/types.ts", "../../src/payments/config/cctp.ts", "../../src/helpers/blockchain.ts", "../../src/helpers/date.ts", "../../src/helpers/types.ts", "../../src/chains/utils/stablecoin.ts", "../../src/payments/config/tokens.ts", "../../src/payments/build.ts", "../../src/payments/comprehensive-payment-request.ts", "../../src/payments/actions/sweep-cctp.ts", "../../src/payments/actions/sweep-erc20.ts", "../../src/payments/actions/sweep-uniswap-v3.ts", "../../src/payments/actions/sweep.ts", "../../src/instructions/contracts/schemas/eip-712/actions/deactivate-instruction.json", "../../src/instructions/contracts/schemas/eip-712/actions/refuel-erc20.json", "../../src/instructions/contracts/schemas/eip-712/actions/refuel.json", "../../src/instructions/contracts/schemas/eip-712/actions/sweep-cctp.json", "../../src/instructions/contracts/schemas/eip-712/actions/sweep-deposit-account-erc20.json", "../../src/instructions/contracts/schemas/eip-712/actions/sweep-deposit-account.json", "../../src/instructions/contracts/schemas/eip-712/actions/sweep-erc20.json", "../../src/instructions/contracts/schemas/eip-712/actions/sweep-skip-cctp-deposit-account.json", "../../src/instructions/contracts/schemas/eip-712/actions/sweep-uniswap-v3.json", "../../src/instructions/contracts/schemas/eip-712/actions/sweep.json", "../../src/instructions/contracts/schemas/eip-712/actions/transfer-erc20.json", "../../src/instructions/contracts/schemas/eip-712/actions/transfer.json", "../../src/instructions/contracts/schemas/eip-712/actions/uniswap-v3-exact-input.json", "../../src/instructions/types.ts", "../../src/payments/instruction-registry.ts", "../../src/payments/action-names.ts", "../../src/payments/validation.ts", "../../src/payments/chain-token-config-builder.ts", "../../src/payments/payment-request-token-resolver.ts", "../../src/payments/payment-metadata-builder.ts"],
4
- "sourcesContent": ["import type { Address, HexString } from \"@otim/utils/schemas\";\n\nexport const PaymentAction = {\n Sweep: \"sweep\",\n SweepCCTP: \"sweepCCTP\",\n SweepERC20: \"sweepERC20\",\n SweepUniswapV3: \"sweepUniswapV3\",\n} as const;\nexport type PaymentAction = (typeof PaymentAction)[keyof typeof PaymentAction];\nexport interface BaseEphemeralInstructionPayload {\n chainId: number;\n maxExecutions: number;\n fee: {\n maxBaseFeePerGas: HexString;\n maxPriorityFeePerGas: HexString;\n token: Address;\n };\n}\n\nexport interface TokenSpec {\n address: Address;\n decimals: number;\n symbol: string;\n}\n\nexport interface PaymentRequestMetadata extends Record<string, unknown> {\n payer?: { name?: string; address?: Address };\n}\n\n/**\n * Uniswap V3 fee tiers. Used to specify the fee tier for a Uniswap V3 swap.\n * @see https://docs.uniswap.org/concepts/protocol/fees\n */\nexport const UniswapV3FeeTier = {\n Lowest: \"100\",\n Low: \"500\",\n Medium: \"3000\",\n High: \"10000\",\n} as const;\nexport type UniswapV3FeeTier =\n (typeof UniswapV3FeeTier)[keyof typeof UniswapV3FeeTier];\n", "import type { Nullable } from \"@otim/utils/helpers\";\n\nimport {\n arbitrum,\n arbitrumSepolia,\n base,\n baseSepolia,\n mainnet,\n optimism,\n optimismSepolia,\n sepolia,\n} from \"viem/chains\";\n\nexport interface CCTPConfig {\n supportedChainIds: Set<number>;\n isSupported(chainId: number): boolean;\n getDomain(chainId: number): Nullable<number>;\n}\n\n/**\n * List of chains that support CCTP\n * Only includes chains that have confirmed CCTP support from Circle\n * @see https://developers.circle.com/stablecoins/docs/supported-domains\n */\nconst cctpSupportedChains = new Set([\n mainnet.id,\n optimism.id,\n arbitrum.id,\n base.id,\n sepolia.id,\n optimismSepolia.id,\n arbitrumSepolia.id,\n baseSepolia.id,\n]);\n\n/**\n * CCTP Domain Mapping - Maps chain IDs to their Circle CCTP domain identifiers\n * Source: https://developers.circle.com/stablecoins/docs/supported-domains\n *\n * Domain IDs are used by Circle's Cross-Chain Transfer Protocol (CCTP) to\n * identify destination chains when burning and minting USDC across different\n * networks.\n */\nconst cctpDomainMapping: Record<number, number> = {\n [mainnet.id]: 0,\n [optimism.id]: 2,\n [arbitrum.id]: 3,\n [base.id]: 6,\n [sepolia.id]: 0,\n [optimismSepolia.id]: 2,\n [arbitrumSepolia.id]: 3,\n [baseSepolia.id]: 6,\n};\n\nexport class DefaultCCTPConfig implements CCTPConfig {\n supportedChainIds: Set<number>;\n\n constructor() {\n this.supportedChainIds = cctpSupportedChains;\n }\n\n isSupported(chainId: number): boolean {\n return this.supportedChainIds.has(chainId);\n }\n\n getDomain(chainId: number): Nullable<number> {\n return cctpDomainMapping[chainId] ?? null;\n }\n}\n\nexport const defaultCCTPConfig = new DefaultCCTPConfig();\n", "import type { EIP2098Signature, HexString, VRS } from \"@otim/utils/schemas\";\nimport type { Chain } from \"viem\";\n\nimport { isAddressEqual } from \"viem\";\n\nexport const truncateAddress = (address: string): string => {\n if (!address) return \"\";\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n};\n\n/**\n * Ethereum address regex pattern\n * Matches addresses like 0x1234...abcd (40 hex characters after 0x prefix)\n */\nexport const ETHEREUM_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/;\n\n/**\n * Validates if a string is a valid Ethereum address format\n * @param address - The address string to validate\n * @returns true if the address matches the Ethereum address format\n */\nexport const isValidEthereumAddress = (address: string): boolean => {\n return ETHEREUM_ADDRESS_REGEX.test(address);\n};\n\n/**\n * Parses a signature string into its v, r, s components.\n * @param signature - The signature string to parse (must be 0x-prefixed, 132 chars total)\n * @returns VRS object containing v, r, and s values\n */\nexport const parseSignatureToVRS = (signature: string): VRS => {\n if (typeof signature !== \"string\") {\n throw new Error(\"Signature must be a string\");\n }\n\n if (!signature.startsWith(\"0x\")) {\n throw new Error('Signature must start with \"0x\"');\n }\n\n if (signature.length !== 132) {\n throw new Error(\n 'Signature must be 65 bytes (130 hex chars) plus \"0x\" = 132 total length',\n );\n }\n\n const r = signature.slice(2, 66);\n const s = signature.slice(66, 130);\n const vHex = signature.slice(130, 132);\n const v = parseInt(vHex, 16);\n return { v, r: `0x${r}`, s: `0x${s}` };\n};\n\n/**\n * Checks if a v value is valid according to EIP-155.\n */\nexport const isValidV = (v: number): boolean => {\n return v === 0 || v === 1 || v === 27 || v === 28 || v >= 35;\n};\n\n/**\n * Normalizes v value for EIP-155 compliance.\n */\nexport const normalizeV = (v: number) => {\n if (!isValidV(v)) return 0;\n\n const cmp = v <= 1 ? 1 : 0;\n const result = v % 2 === cmp;\n\n return Number(result) % 2;\n};\n\n/**\n * Creates an EIP-2098 compact signature from VRS components.\n * @param vrs - The VRS signature components\n * @returns EIP2098Signature object with yParity, r, and s\n */\nexport const createEIP2098Signature = (vrs: VRS): EIP2098Signature => {\n const v = vrs.v;\n const r = vrs.r;\n const s = vrs.s;\n\n return { yParity: normalizeV(v), r, s };\n};\n\nexport const getChainRpcUrl = (\n chainId: number,\n chains: readonly [Chain, ...Chain[]],\n) => {\n const chain = chains.find((chain) => chain.id === chainId);\n return chain?.rpcUrls.default;\n};\n\nexport const DEFAULT_ADDRESS = \"0x0000000000000000000000000000000000000000\";\n\nexport const isNullAddress = (address: HexString) => {\n return isAddressEqual(address, DEFAULT_ADDRESS);\n};\n", "import z from \"zod\";\n\nimport { logger } from \"./logger\";\n\ntype Locale = \"en\" | \"es\";\n\ntype FormatDateFunc<T> = (date: Date) => T;\n\nexport const iso8601DateSchema = z\n .string()\n .regex(\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$/,\n \"Must be a valid ISO 8601 date format (e.g., 2024-12-31T23:59:59.000Z)\",\n );\n\nexport const TimeUnit = {\n Day: \"day\",\n Month: \"month\",\n Year: \"year\",\n} as const;\n\nexport type TimeUnit = (typeof TimeUnit)[keyof typeof TimeUnit];\n\nconst units = {\n [TimeUnit.Day]: {\n one: \"day\",\n other: \"days\",\n },\n [TimeUnit.Month]: {\n one: \"month\",\n other: \"months\",\n },\n [TimeUnit.Year]: {\n one: \"year\",\n other: \"years\",\n },\n} as const;\n\nconst formatDateAsUSStandard = (\n date: Date,\n opts?: Intl.DateTimeFormatOptions,\n) =>\n date.toLocaleString(\"en-US\", {\n month: \"2-digit\",\n day: \"2-digit\",\n year: \"numeric\",\n ...opts,\n });\n\nexport const formatDateAsISO = (date: Date) => date.toISOString();\n\nconst formatFullDate = (date: Date): string => {\n const options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"long\",\n day: \"2-digit\",\n timeZone: \"UTC\",\n };\n return new Intl.DateTimeFormat(\"en-US\", options).format(date);\n};\n\nconst formatTime = (date: Date): string => {\n return date.toLocaleTimeString(\"en-US\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n timeZone: \"UTC\",\n timeZoneName: \"short\",\n });\n};\n\nconst formatDateTime = (date: Date): string => {\n const dateOptions: Intl.DateTimeFormatOptions = {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n timeZone: \"UTC\",\n };\n const timeOptions: Intl.DateTimeFormatOptions = {\n hour: \"2-digit\",\n minute: \"2-digit\",\n timeZone: \"UTC\",\n };\n\n const formattedDate = new Intl.DateTimeFormat(\"en-US\", dateOptions).format(\n date,\n );\n const formattedTime = new Intl.DateTimeFormat(\"en-US\", timeOptions).format(\n date,\n );\n\n return `${formattedDate} at ${formattedTime}`;\n};\n\n/**\n * Formats a date in long format (e.g., \"June 19, 2025\")\n * @param date - Date object to format\n * @returns Formatted date string\n */\nconst formatLongDate = (date: Date): string => {\n const options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n timeZone: \"UTC\",\n };\n return new Intl.DateTimeFormat(\"en-US\", options).format(date);\n};\n\n/**\n * Formats a date with time in long format (e.g., \"June 19, 2025 at 07:00 AM\")\n * @param date - Date object to format\n * @returns Formatted date and time string\n */\nconst formatLongDateTime = (date: Date): string => {\n const dateOptions: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n timeZone: \"UTC\",\n };\n const timeOptions: Intl.DateTimeFormatOptions = {\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: true,\n timeZone: \"UTC\",\n };\n\n const formattedDate = new Intl.DateTimeFormat(\"en-US\", dateOptions).format(\n date,\n );\n const formattedTime = new Intl.DateTimeFormat(\"en-US\", timeOptions)\n .format(date)\n .toLowerCase();\n\n return `${formattedDate} at ${formattedTime}`;\n};\n\nconst formatToShortDate = (dateString: string | Date) => {\n const date =\n typeof dateString === \"string\" ? new Date(dateString) : dateString;\n\n if (isNaN(date.getTime())) {\n return \"Jan 1\";\n }\n\n return date.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n timeZone: \"UTC\",\n });\n};\n\nconst formatToShortDateWithYear = (dateString: string | Date) => {\n const date =\n typeof dateString === \"string\" ? new Date(dateString) : dateString;\n\n if (isNaN(date.getTime())) {\n return \"Unknown\";\n }\n\n return date.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n timeZone: \"UTC\",\n });\n};\n\nexport const formatToJustDate = (dateString: string) => {\n const date = new Date(dateString);\n\n if (isNaN(date.getTime())) {\n return \"1\";\n }\n\n return date.getUTCDate().toString();\n};\n\nexport const formatDateToYYYYMMDD = (date: Date) => {\n return new Intl.DateTimeFormat(\"en-CA\", {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n }).format(date);\n};\n\nconst isDateInvalid = (date: Date) => {\n return date.toString() === \"Invalid Date\";\n};\n\n/**\n * Validates if a date is valid (opposite of isDateInvalid)\n * Checks both the Date object validity and the timestamp\n */\nconst isValidDate = (date: Date): boolean => {\n return !isDateInvalid(date) && !isNaN(date.getTime());\n};\n\nconst isDateEpoc = (date: Date) => {\n return date.getTime() <= 0;\n};\n\nconst isDateInRange = (arg: unknown): boolean => {\n if (typeof arg !== \"string\") {\n return false;\n }\n\n const date = new Date(arg);\n const startDate = new Date(\"1800-01-01T00:00:00.000Z\");\n const endDate = new Date(\"2999-12-31T23:59:59.999Z\");\n\n return date >= startDate && date <= endDate;\n};\n\nconst isDateInPast = (input: string | number | Date): boolean => {\n let date: Date;\n if (input instanceof Date) {\n date = input;\n } else if (typeof input === \"number\") {\n const ms = input < 1e12 ? input * 1000 : input;\n date = new Date(ms);\n } else {\n date = new Date(input);\n }\n\n if (isNaN(date.getTime())) {\n return false;\n }\n\n return date.getTime() < Date.now();\n};\n\nconst isSameDate = (dateA: Date, dateB: Date) => {\n return (\n dateA.getFullYear() === dateB.getFullYear() &&\n dateA.getMonth() === dateB.getMonth() &&\n dateA.getDate() === dateB.getDate()\n );\n};\n\nconst getPluralizedUnit = (\n unit: keyof typeof units,\n count: number,\n locale: Locale = \"en\",\n) => {\n const pluralRules = new Intl.PluralRules(locale, {\n type: \"cardinal\",\n });\n const pluralCategory = pluralRules.select(count);\n\n if (pluralCategory === \"one\" || pluralCategory === \"other\") {\n return `${count} ${units[unit][pluralCategory]}`;\n }\n\n return `${count} ${units[unit].other}`;\n};\n\nconst getRelativeDateDescription = (\n targetDate: Date,\n locale: Locale = \"en\",\n) => {\n const currentDate = new Date();\n\n const oneDay = 1000 * 60 * 60 * 24;\n const oneMonth = oneDay * 30;\n const oneYear = oneDay * 365;\n\n const diffInMilliseconds = targetDate.getTime() - currentDate.getTime();\n const diffInDays = Math.round(diffInMilliseconds / oneDay);\n const diffInMonths = Math.round(diffInMilliseconds / oneMonth);\n const diffInYears = Math.round(diffInMilliseconds / oneYear);\n\n if (Math.abs(diffInYears) >= 1) {\n return getPluralizedUnit(\"year\", Math.abs(diffInYears), locale);\n }\n\n if (Math.abs(diffInMonths) >= 1) {\n return getPluralizedUnit(\"month\", Math.abs(diffInMonths), locale);\n }\n\n return getPluralizedUnit(\"day\", Math.abs(diffInDays), locale);\n};\n\n/**\n * Safely formats a date with validation and fallback support\n * @param date - String or Date to format\n * @param formatter - Function that formats the Date object\n * @param fallback - Value to return if date is invalid\n * @returns Formatted string or fallback value\n */\nconst safeFormatDate = <T = string>(\n date: string | Date,\n formatter: FormatDateFunc<T>,\n fallback: T,\n): T => {\n const dateObj = typeof date === \"string\" ? new Date(date) : date;\n\n if (!isValidDate(dateObj)) {\n return fallback;\n }\n\n try {\n return formatter(dateObj);\n } catch (error) {\n logger.logError(error, {\n context: safeFormatDate.name,\n });\n return fallback;\n }\n};\n\nconst parseDateTime = (dateInput: string, timeInput?: string) => {\n const dateRegex = /^(\\d{1,2})\\/(\\d{1,2})\\/(\\d{4})$/;\n const timeRegex = /^(\\d{1,2}):(\\d{2})(?::(\\d{2}))?\\s*(AM|PM|am|pm)?$/;\n\n const dateMatch = dateRegex.exec(dateInput);\n if (!dateMatch) {\n return undefined;\n }\n\n const month = parseInt(dateMatch[1]!, 10) - 1;\n const day = parseInt(dateMatch[2]!, 10);\n const year = parseInt(dateMatch[3]!, 10);\n\n let hours = 0;\n let minutes = 0;\n let seconds = 0;\n\n if (timeInput) {\n timeInput = timeInput.replace(/\\u00A0/g, \" \").trim();\n\n const timeMatch = timeRegex.exec(timeInput);\n if (!timeMatch) {\n return undefined;\n }\n\n hours = parseInt(timeMatch[1]!, 10);\n minutes = parseInt(timeMatch[2]!, 10);\n seconds = timeMatch[3] ? parseInt(timeMatch[3], 10) : 0;\n const meridiem = timeMatch[4] ? timeMatch[4].toUpperCase() : null;\n\n if (meridiem === \"PM\" && hours < 12) {\n hours += 12;\n } else if (meridiem === \"AM\" && hours === 12) {\n hours = 0;\n }\n }\n\n const date = new Date(Date.UTC(year, month, day, hours, minutes, seconds));\n if (isNaN(date.getTime())) {\n return undefined;\n }\n\n return date;\n};\n\nconst validateIso8601Date = (dueDate: string): void => {\n const result = iso8601DateSchema.safeParse(dueDate);\n if (!result.success) {\n const errorMessage =\n result.error.issues[0]?.message || \"Invalid ISO 8601 format\";\n throw new Error(`Invalid due date format: ${errorMessage}`);\n }\n};\n\nexport {\n formatDateAsUSStandard,\n formatToShortDate,\n formatToShortDateWithYear,\n formatFullDate,\n formatTime,\n formatDateTime,\n formatLongDate,\n formatLongDateTime,\n getPluralizedUnit,\n getRelativeDateDescription,\n isDateInvalid,\n isValidDate,\n validateIso8601Date,\n isDateEpoc,\n isDateInRange,\n isDateInPast,\n isSameDate,\n safeFormatDate,\n parseDateTime,\n};\nexport type { FormatDateFunc };\n", "import type { z, ZodObject } from \"zod\";\n\nexport type Nullable<T> = T | null;\nexport type Nullish<T> = T | null | undefined;\nexport type Optional<T> = T | undefined;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- any is ok\nexport type Any = any;\n\nexport type NumberOrString = number | string;\n\nexport type OverrideProps<T, TOverridden> = Omit<T, keyof TOverridden> &\n TOverridden;\n\nexport type NonEmptyArray<T> = [T, ...T[]];\n\nexport interface DataRecord {\n [value: string]: Nullish<DataRecord | string | number | boolean>;\n}\n\nexport interface Input<T> {\n input: T;\n}\n\nexport type ZodCustom<Values extends object> = ZodObject<{\n [P in keyof Values]: z.ZodType<Values[P]>;\n}>;\n\nexport const isError = (value: unknown): value is Error =>\n value instanceof Error;\n\nexport const isFunction = (\n value: unknown,\n): value is (...args: unknown[]) => unknown => typeof value === \"function\";\n\nexport const isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nexport const isNumber = (value: unknown): value is number =>\n typeof value === \"number\";\n\nexport const isString = (value: unknown): value is string =>\n typeof value === \"string\";\n\nexport const isUndefined = (value: unknown): value is undefined =>\n typeof value === \"undefined\";\n\nexport const isBoolean = (value: unknown): value is boolean =>\n typeof value === \"boolean\";\n\n/**\n * Safely extracts a string from an unknown value.\n * @param value - The value to extract from\n * @param fallback - Optional fallback value if extraction fails\n * @returns The extracted string or fallback/undefined\n */\nexport const extractString = (\n value: unknown,\n fallback?: string,\n): Optional<string> => {\n return isString(value) ? value : fallback;\n};\n\n/**\n * Safely extracts a number from an unknown value.\n * Handles both number and string representations.\n * @param value - The value to extract from\n * @returns The extracted number or undefined\n */\nexport const extractNumber = (value: unknown): Optional<number> => {\n if (isNumber(value)) {\n return value;\n }\n\n if (isString(value)) {\n const parsed = Number.parseFloat(value);\n return Number.isNaN(parsed) ? undefined : parsed;\n }\n\n return undefined;\n};\n", "/**\n * List of supported stablecoin symbols\n */\nconst stablecoinSymbols = [\"USDC\", \"USDT\"] as const;\n\n/**\n * Checks if a token symbol is a stablecoin\n * @param symbol - Token symbol to check (e.g., \"USDC\", \"ETH\")\n * @returns true if the symbol is a recognized stablecoin\n */\nexport function isStablecoin(symbol: string | string[]): boolean {\n if (typeof symbol === \"string\") {\n return stablecoinSymbols.includes(\n symbol as (typeof stablecoinSymbols)[number],\n );\n }\n\n return symbol.every((s) =>\n stablecoinSymbols.includes(s as (typeof stablecoinSymbols)[number]),\n );\n}\n", "import { isStablecoin } from \"@otim/utils/chains\";\n\nimport { UniswapV3FeeTier } from \"../types\";\n\n/**\n * Determines the recommended Uniswap V3 fee tier for a token pair\n *\n * Stable pairs (USDC/USDT swaps) use the Low fee tier (0.05%) since price\n * volatility is minimal. All other pairs use the Medium fee tier (0.3%) to\n * account for higher price volatility\n *\n * @param tokenIn - Symbol of the input token (e.g., \"USDC\", \"USDT\")\n * @param tokenOut - Symbol of the output token (e.g., \"USDC\", \"USDT\")\n * @returns The recommended Uniswap V3 fee tier for the swap\n */\nexport function getRecommendedFeeTier(\n tokenIn: string,\n tokenOut: string,\n): UniswapV3FeeTier {\n if (isStablecoin([tokenIn, tokenOut])) {\n return UniswapV3FeeTier.Low;\n }\n\n return UniswapV3FeeTier.Medium;\n}\n", "import type { PaymentRequestMetadata } from \"./types\";\nimport type { PaymentRequestBuildRequest } from \"@otim/utils/api\";\nimport type { Nullable } from \"@otim/utils/helpers\";\nimport type { Address, HexString } from \"@otim/utils/schemas\";\n\nimport { DEFAULT_ADDRESS } from \"@otim/utils/helpers\";\n\nexport interface EphemeralInstructionSpec {\n chainId: number;\n salt?: number;\n maxExecutions: number;\n actionArguments: Record<string, unknown>;\n setEphemeralTarget?: boolean;\n}\n\nexport interface BuildPaymentRequestParams {\n payerAddress?: Nullable<Address>;\n completionInstructions: EphemeralInstructionSpec[];\n instructions?: EphemeralInstructionSpec[];\n metadata?: PaymentRequestMetadata;\n}\n\ninterface ProcessedInstruction {\n chainId: number;\n salt: number;\n maxExecutions: number;\n actionArguments: Record<string, unknown>;\n setEphemeralTarget: boolean;\n}\n\nexport interface FeeConfig {\n executionFee: number;\n maxBaseFeePerGas: `0x${string}`;\n maxPriorityFeePerGas: `0x${string}`;\n token: Address;\n}\n\nconst DEFAULT_SET_EPHEMERAL_TARGET = true;\n\nexport function createPaymentRequestBuildPayload(\n params: BuildPaymentRequestParams,\n): PaymentRequestBuildRequest {\n const {\n payerAddress = null,\n completionInstructions,\n instructions = [],\n metadata = {},\n } = params;\n\n return {\n payerAddress,\n completionInstructions: completionInstructions.map(processInstruction),\n instructions: instructions.map(processInstruction),\n metadata,\n };\n}\n\nfunction processInstruction(\n spec: EphemeralInstructionSpec,\n): ProcessedInstruction {\n return {\n chainId: spec.chainId,\n salt: spec.salt ?? generateRandomSalt(),\n maxExecutions: spec.maxExecutions,\n actionArguments: spec.actionArguments,\n setEphemeralTarget: spec.setEphemeralTarget ?? DEFAULT_SET_EPHEMERAL_TARGET,\n };\n}\n\nfunction generateRandomSalt(): number {\n return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);\n}\n\nexport function createDefaultFee(\n executionFee = 0,\n maxBaseFeePerGas: HexString = \"0x0\",\n maxPriorityFeePerGas: HexString = \"0x0\",\n token: Address = DEFAULT_ADDRESS,\n): FeeConfig {\n return {\n token,\n executionFee,\n maxBaseFeePerGas,\n maxPriorityFeePerGas,\n };\n}\n\nexport function createFeeWithToken(\n token?: Address,\n maxPriorityFeePerGas?: `0x${string}`,\n): FeeConfig {\n return createDefaultFee(0, \"0x0\", maxPriorityFeePerGas ?? \"0x0\", token);\n}\n", "import type { EphemeralInstructionSpec } from \"./build\";\nimport type { CCTPConfig } from \"./config/cctp\";\nimport type { PaymentRequestMetadata } from \"./types\";\nimport type { PaymentRequestBuildRequest } from \"@otim/utils/api\";\nimport type { Address } from \"@otim/utils/schemas\";\n\nimport { parseUnits, toHex } from \"viem\";\n\nimport { isStablecoin } from \"@otim/utils/chains\";\n\nimport { createSweepCCTPActionArguments } from \"./actions/sweep-cctp\";\nimport { createSweepERC20ActionArguments } from \"./actions/sweep-erc20\";\nimport { createSweepUniswapV3ActionArguments } from \"./actions/sweep-uniswap-v3\";\nimport { createFeeWithToken, createPaymentRequestBuildPayload } from \"./build\";\nimport { defaultCCTPConfig } from \"./config/cctp\";\nimport { getRecommendedFeeTier } from \"./config/tokens\";\n\nexport interface ChainTokenConfig {\n chainId: number;\n tokens: Array<{\n symbol: string;\n address: Address;\n decimals: number;\n }>;\n}\n\nexport interface ComprehensivePaymentRequestParams {\n settlementChainId: number;\n recipient: Address;\n amount: string;\n ephemeralWalletAddress: Address;\n chainTokenConfigs: ChainTokenConfig[];\n payerAddress?: Address | null;\n metadata?: PaymentRequestMetadata;\n feeToken?: Address;\n cctpConfig?: CCTPConfig;\n}\n\ninterface SettlementTokenInfo {\n address: Address;\n decimals: number;\n}\n\nconst USDC_SYMBOL = \"USDC\";\nconst USDT_SYMBOL = \"USDT\";\nconst MINIMUM_THRESHOLD = 1n;\nconst UNISWAP_MEAN_PRICE_LOOKBACK = 600;\n\n/**\n * For payment requests, endBalance is always 0 across all instruction types\n * (Sweep, SweepERC20, SweepCCTP, SweepUniswapV3). This ensures all available\n * tokens are swept/bridged/swapped without leaving dust in the ephemeral\n * wallet.\n */\nconst ZERO_BALANCE = 0n;\n\nconst USDT_MAX_PRICE_DEVIATION_BPS = 200;\nconst DEFAULT_MAX_PRICE_DEVIATION_BPS = 500;\n\nconst STABLE_SLIPPAGE_BPS = 1;\nconst NON_STABLE_SLIPPAGE_BPS = 50;\n\nexport function createComprehensivePaymentRequest(\n params: ComprehensivePaymentRequestParams,\n): PaymentRequestBuildRequest {\n const {\n settlementChainId,\n recipient,\n amount,\n ephemeralWalletAddress,\n chainTokenConfigs,\n payerAddress,\n metadata,\n feeToken,\n cctpConfig = defaultCCTPConfig,\n } = params;\n\n validateSettlementChainSupport(settlementChainId, cctpConfig);\n\n const settlementConfig = findChainConfig(\n settlementChainId,\n chainTokenConfigs,\n );\n const settlementUSDC = findSettlementUSDC(settlementConfig);\n const threshold = calculateThreshold(amount, settlementUSDC.decimals);\n\n /**\n * For payment requests, we don't charge in-protocol fees, so all fee values\n * are set to zero. This provides slight gas savings by pushing fewer non-zero\n * bytes on-chain.\n */\n const instructionFee = createFeeWithToken(feeToken);\n\n const completionInstructions = createCompletionInstructions(\n settlementChainId,\n settlementUSDC.address,\n recipient,\n threshold,\n instructionFee,\n chainTokenConfigs,\n );\n\n const instructions = createCrossChainInstructions(\n chainTokenConfigs,\n settlementChainId,\n ephemeralWalletAddress,\n instructionFee,\n cctpConfig,\n );\n\n return createPaymentRequestBuildPayload({\n payerAddress,\n completionInstructions,\n instructions,\n metadata,\n });\n}\n\nfunction validateSettlementChainSupport(\n chainId: number,\n cctpConfig: CCTPConfig,\n): void {\n if (!cctpConfig.isSupported(chainId)) {\n throw new Error(`Settlement chain ${chainId} does not support CCTP`);\n }\n}\n\nfunction findChainConfig(\n chainId: number,\n configs: ChainTokenConfig[],\n): ChainTokenConfig {\n const config = configs.find((c) => c.chainId === chainId);\n\n if (!config) {\n throw new Error(\n `Settlement chain ${chainId} not found in chain token configs`,\n );\n }\n\n return config;\n}\n\nfunction findSettlementUSDC(\n settlementConfig: ChainTokenConfig,\n): SettlementTokenInfo {\n const usdc = settlementConfig.tokens.find(\n (token) => token.symbol.toUpperCase() === USDC_SYMBOL,\n );\n\n if (!usdc) {\n throw new Error(\n `Settlement chain ${settlementConfig.chainId} does not have USDC configured`,\n );\n }\n\n return {\n address: usdc.address,\n decimals: usdc.decimals,\n };\n}\n\nfunction calculateThreshold(amount: string, decimals: number): `0x${string}` {\n return toHex(parseUnits(amount, decimals));\n}\n\nfunction createCompletionInstructions(\n settlementChainId: number,\n settlementUSDCAddress: Address,\n recipient: Address,\n threshold: `0x${string}`,\n instructionFee: ReturnType<typeof createFeeWithToken>,\n chainTokenConfigs: ChainTokenConfig[],\n): EphemeralInstructionSpec[] {\n const instructions: EphemeralInstructionSpec[] = [];\n\n instructions.push(\n createSettlementSweepInstruction(\n settlementChainId,\n settlementUSDCAddress,\n recipient,\n threshold,\n instructionFee,\n ),\n );\n\n const swapInstructions = createTokenSwapInstructions(\n settlementChainId,\n chainTokenConfigs,\n recipient,\n threshold,\n instructionFee,\n );\n\n instructions.push(...swapInstructions);\n\n return instructions;\n}\n\n/**\n * Creates the final settlement sweep instruction that sends USDC to the\n * recipient. For payment requests, endBalance is always 0 to sweep all\n * available tokens.\n */\nfunction createSettlementSweepInstruction(\n chainId: number,\n tokenAddress: Address,\n recipient: Address,\n threshold: `0x${string}`,\n fee: ReturnType<typeof createFeeWithToken>,\n): EphemeralInstructionSpec {\n return {\n chainId,\n maxExecutions: 1,\n actionArguments: createSweepERC20ActionArguments({\n chainId,\n maxExecutions: 1,\n token: tokenAddress,\n target: recipient,\n threshold,\n endBalance: toHex(ZERO_BALANCE),\n fee,\n }),\n setEphemeralTarget: false,\n };\n}\n\nfunction createTokenSwapInstructions(\n settlementChainId: number,\n chainTokenConfigs: ChainTokenConfig[],\n settlementRecipient: Address,\n threshold: `0x${string}`,\n instructionFee: ReturnType<typeof createFeeWithToken>,\n): EphemeralInstructionSpec[] {\n const swapInstructions: EphemeralInstructionSpec[] = [];\n\n const settlementConfig = chainTokenConfigs.find(\n (c) => c.chainId === settlementChainId,\n );\n\n if (!settlementConfig) {\n return swapInstructions;\n }\n\n const settlementUSDC = settlementConfig.tokens.find(\n (t) => t.symbol.toUpperCase() === USDC_SYMBOL,\n );\n\n if (!settlementUSDC) {\n return swapInstructions;\n }\n\n for (const sourceToken of settlementConfig.tokens) {\n if (sourceToken.symbol.toUpperCase() === USDC_SYMBOL) {\n continue;\n }\n\n const swapInstruction = createSwapInstruction(\n settlementChainId,\n sourceToken,\n settlementUSDC,\n settlementRecipient,\n threshold,\n instructionFee,\n );\n\n swapInstructions.push(swapInstruction);\n }\n\n return swapInstructions;\n}\n\n/**\n * Creates a Uniswap V3 swap instruction as a completion instruction.\n * Uses appropriate slippage tolerance based on token pair (tighter for\n * stables). For payment requests, endBalance is always 0.\n */\nfunction createSwapInstruction(\n chainId: number,\n tokenIn: ChainTokenConfig[\"tokens\"][number],\n tokenOut: ChainTokenConfig[\"tokens\"][number],\n settlementRecipient: Address,\n threshold: `0x${string}`,\n fee: ReturnType<typeof createFeeWithToken>,\n): EphemeralInstructionSpec {\n const { instruction } = createSwapInstructionWithFloor(\n chainId,\n tokenIn,\n tokenOut,\n settlementRecipient,\n threshold,\n fee,\n false,\n );\n return instruction;\n}\n\n/**\n * Creates a Uniswap V3 swap instruction and returns both the instruction\n * and the calculated floorAmountOut for downstream threshold calculations.\n */\nfunction createSwapInstructionWithFloor(\n chainId: number,\n tokenIn: ChainTokenConfig[\"tokens\"][number],\n tokenOut: ChainTokenConfig[\"tokens\"][number],\n recipient: Address,\n threshold: `0x${string}`,\n fee: ReturnType<typeof createFeeWithToken>,\n setEphemeralTarget: boolean,\n): { instruction: EphemeralInstructionSpec; floorAmountOut: bigint } {\n const feeTier = getRecommendedFeeTier(\n tokenIn.symbol.toUpperCase(),\n USDC_SYMBOL,\n );\n\n const isStableToStableSwap = isStablecoin([\n tokenIn.symbol.toUpperCase(),\n tokenOut.symbol.toUpperCase(),\n ]);\n\n const slippageBps = isStableToStableSwap\n ? STABLE_SLIPPAGE_BPS\n : NON_STABLE_SLIPPAGE_BPS;\n\n const maxPriceDeviationBps =\n tokenIn.symbol.toUpperCase() === USDT_SYMBOL\n ? USDT_MAX_PRICE_DEVIATION_BPS\n : DEFAULT_MAX_PRICE_DEVIATION_BPS;\n\n const baseAmount = BigInt(threshold);\n const afterFeeAmount =\n (baseAmount * BigInt(1000000 - Number(feeTier))) / 1000000n;\n const floorAmountOut =\n (afterFeeAmount * BigInt(10000 - slippageBps)) / 10000n;\n\n const instruction: EphemeralInstructionSpec = {\n chainId,\n maxExecutions: 1,\n actionArguments: createSweepUniswapV3ActionArguments({\n chainId,\n maxExecutions: 1,\n recipient,\n tokenIn: tokenIn.address,\n tokenOut: tokenOut.address,\n feeTier,\n threshold,\n endBalance: toHex(ZERO_BALANCE),\n floorAmountOut: toHex(floorAmountOut),\n meanPriceLookBack: UNISWAP_MEAN_PRICE_LOOKBACK,\n maxPriceDeviationBps,\n fee,\n }),\n setEphemeralTarget,\n };\n\n return { instruction, floorAmountOut };\n}\n\n/**\n * Creates swap instructions for non-USDC tokens on non-settlement chains.\n * These swaps send to the ephemeral wallet so the resulting USDC can be\n * bridged.\n *\n * For cross-chain swaps, we set floorAmountOut to 0 because we cannot predict\n * the actual amount that will be swapped. The TWAP oracle provides price\n * manipulation protection at execution time based on the actual swap amount.\n */\nfunction createCrossChainSwapInstructions(\n chainConfig: ChainTokenConfig,\n chainUSDC: ChainTokenConfig[\"tokens\"][number],\n ephemeralWalletAddress: Address,\n instructionFee: ReturnType<typeof createFeeWithToken>,\n): EphemeralInstructionSpec[] {\n const swapInstructions: EphemeralInstructionSpec[] = [];\n\n for (const sourceToken of chainConfig.tokens) {\n if (sourceToken.symbol.toUpperCase() === USDC_SYMBOL) {\n continue;\n }\n\n const feeTier = getRecommendedFeeTier(\n sourceToken.symbol.toUpperCase(),\n USDC_SYMBOL,\n );\n\n const maxPriceDeviationBps =\n sourceToken.symbol.toUpperCase() === USDT_SYMBOL\n ? USDT_MAX_PRICE_DEVIATION_BPS\n : DEFAULT_MAX_PRICE_DEVIATION_BPS;\n\n const instruction: EphemeralInstructionSpec = {\n chainId: chainConfig.chainId,\n maxExecutions: 1,\n actionArguments: createSweepUniswapV3ActionArguments({\n chainId: chainConfig.chainId,\n maxExecutions: 1,\n recipient: ephemeralWalletAddress,\n tokenIn: sourceToken.address,\n tokenOut: chainUSDC.address,\n feeTier,\n threshold: toHex(MINIMUM_THRESHOLD),\n endBalance: toHex(ZERO_BALANCE),\n floorAmountOut: toHex(0n),\n meanPriceLookBack: UNISWAP_MEAN_PRICE_LOOKBACK,\n maxPriceDeviationBps,\n fee: instructionFee,\n }),\n setEphemeralTarget: true,\n };\n\n swapInstructions.push(instruction);\n }\n\n return swapInstructions;\n}\n\nfunction createCrossChainInstructions(\n chainTokenConfigs: ChainTokenConfig[],\n settlementChainId: number,\n ephemeralWalletAddress: Address,\n instructionFee: ReturnType<typeof createFeeWithToken>,\n cctpConfig: CCTPConfig,\n): EphemeralInstructionSpec[] {\n const instructions: EphemeralInstructionSpec[] = [];\n\n for (const chainConfig of chainTokenConfigs) {\n if (chainConfig.chainId === settlementChainId) {\n continue;\n }\n\n const chainUSDC = chainConfig.tokens.find(\n (token) => token.symbol.toUpperCase() === USDC_SYMBOL,\n );\n\n if (!chainUSDC || !cctpConfig.isSupported(chainConfig.chainId)) {\n continue;\n }\n\n const swapInstructions = createCrossChainSwapInstructions(\n chainConfig,\n chainUSDC,\n ephemeralWalletAddress,\n instructionFee,\n );\n\n instructions.push(...swapInstructions);\n\n const bridgeInstruction = createCCTPBridgeInstruction(\n chainConfig.chainId,\n chainUSDC.address,\n settlementChainId,\n ephemeralWalletAddress,\n toHex(MINIMUM_THRESHOLD),\n instructionFee,\n cctpConfig,\n );\n\n instructions.push(bridgeInstruction);\n }\n\n return instructions;\n}\n\n/**\n * Creates a CCTP bridge instruction to move USDC across chains.\n * For payment requests, endBalance is always 0 to bridge all available USDC.\n *\n * The threshold is set to MINIMUM_THRESHOLD (1 wei) so the bridge executes\n * as soon as any USDC is available from upstream swaps, regardless of the\n * actual amount swapped (which is unpredictable).\n */\nfunction createCCTPBridgeInstruction(\n sourceChainId: number,\n tokenAddress: Address,\n destinationChainId: number,\n ephemeralWalletAddress: Address,\n threshold: `0x${string}`,\n fee: ReturnType<typeof createFeeWithToken>,\n cctpConfig: CCTPConfig,\n): EphemeralInstructionSpec {\n return {\n chainId: sourceChainId,\n maxExecutions: 1,\n actionArguments: createSweepCCTPActionArguments({\n chainId: sourceChainId,\n maxExecutions: 1,\n token: tokenAddress,\n destinationChainId,\n destinationMintRecipient: ephemeralWalletAddress,\n threshold,\n endBalance: toHex(ZERO_BALANCE),\n fee,\n cctpConfig,\n }),\n setEphemeralTarget: true,\n };\n}\n", "import type { CCTPConfig } from \"../config/cctp\";\nimport type { BaseEphemeralInstructionPayload } from \"../types\";\nimport type { Address } from \"@otim/utils/schemas\";\n\nimport { pad } from \"viem\";\n\nimport { defaultCCTPConfig } from \"../config/cctp\";\nimport { PaymentAction } from \"../types\";\n\nexport interface SweepCCTPEphemeralPayload\n extends BaseEphemeralInstructionPayload {\n token: Address;\n destinationChainId: number;\n destinationMintRecipient: Address;\n threshold: string;\n endBalance: string;\n cctpConfig?: CCTPConfig;\n}\n\ntype SweepCCTPActionArguments = Record<string, unknown>;\n\nexport function createSweepCCTPActionArguments(\n payload: SweepCCTPEphemeralPayload,\n): SweepCCTPActionArguments {\n const cctpConfig = payload.cctpConfig ?? defaultCCTPConfig;\n const destinationDomain = resolveCCTPDomain(\n payload.destinationChainId,\n cctpConfig,\n );\n\n return {\n [PaymentAction.SweepCCTP]: {\n token: payload.token,\n destinationDomain,\n /* CCTP requires the recipient address to be padded to 32 bytes */\n destinationMintRecipient: pad(payload.destinationMintRecipient, {\n size: 32,\n }),\n threshold: payload.threshold,\n endBalance: payload.endBalance,\n fee: payload.fee,\n },\n };\n}\n\nfunction resolveCCTPDomain(\n destinationChainId: number,\n cctpConfig: CCTPConfig,\n): number {\n const domain = cctpConfig.getDomain(destinationChainId);\n\n if (domain === null) {\n throw new Error(`Chain ${destinationChainId} does not support CCTP`);\n }\n\n return domain;\n}\n", "import type { BaseEphemeralInstructionPayload } from \"../types\";\nimport type { Address } from \"@otim/utils/schemas\";\n\nimport { PaymentAction } from \"../types\";\n\nexport interface SweepERC20EphemeralPayload\n extends BaseEphemeralInstructionPayload {\n token: Address;\n target: Address;\n threshold: string;\n endBalance: string;\n}\n\ntype SweepERC20ActionArguments = Record<string, unknown>;\n\nexport function createSweepERC20ActionArguments(\n payload: SweepERC20EphemeralPayload,\n): SweepERC20ActionArguments {\n return {\n [PaymentAction.SweepERC20]: {\n token: payload.token,\n target: payload.target,\n threshold: payload.threshold,\n endBalance: payload.endBalance,\n fee: payload.fee,\n },\n };\n}\n", "import type {\n BaseEphemeralInstructionPayload,\n UniswapV3FeeTier,\n} from \"../types\";\nimport type { Address } from \"@otim/utils/schemas\";\n\nimport { PaymentAction } from \"../types\";\n\nexport interface SweepUniswapV3EphemeralPayload\n extends BaseEphemeralInstructionPayload {\n recipient: Address;\n tokenIn: Address;\n tokenOut: Address;\n feeTier: UniswapV3FeeTier;\n threshold: string;\n endBalance: string;\n floorAmountOut: string;\n meanPriceLookBack: number;\n maxPriceDeviationBps: number;\n}\n\ntype SweepUniswapV3ActionArguments = Record<string, unknown>;\n\nexport function createSweepUniswapV3ActionArguments(\n payload: SweepUniswapV3EphemeralPayload,\n): SweepUniswapV3ActionArguments {\n return {\n [PaymentAction.SweepUniswapV3]: {\n recipient: payload.recipient,\n tokenIn: payload.tokenIn,\n tokenOut: payload.tokenOut,\n feeTier: payload.feeTier,\n threshold: payload.threshold,\n endBalance: payload.endBalance,\n floorAmountOut: payload.floorAmountOut,\n meanPriceLookBack: payload.meanPriceLookBack,\n maxPriceDeviationBps: payload.maxPriceDeviationBps,\n fee: payload.fee,\n },\n };\n}\n", "import type { BaseEphemeralInstructionPayload } from \"../types\";\nimport type { Address } from \"@otim/utils/schemas\";\n\nimport { toHex } from \"viem\";\n\nimport { PaymentAction } from \"../types\";\n\nexport interface SweepEphemeralPayload extends BaseEphemeralInstructionPayload {\n target: Address;\n threshold: string;\n endBalance: string;\n gasLimit: number;\n}\n\ntype SweepActionArguments = Record<string, unknown>;\n\nexport function createSweepActionArguments(\n payload: SweepEphemeralPayload,\n): SweepActionArguments {\n return {\n [PaymentAction.Sweep]: {\n target: payload.target,\n threshold: payload.threshold,\n endBalance: payload.endBalance,\n gasLimit: toHex(payload.gasLimit),\n fee: payload.fee,\n },\n };\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"deactivateInstruction\", \"type\": \"DeactivateInstruction\" }\n ],\n \"DeactivateInstruction\": [\n { \"name\": \"instructionId\", \"type\": \"bytes32\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"refuelERC20\", \"type\": \"RefuelERC20\" }\n ],\n \"RefuelERC20\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"target\", \"type\": \"address\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"endBalance\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"refuel\", \"type\": \"Refuel\" }\n ],\n \"Refuel\": [\n { \"name\": \"target\", \"type\": \"address\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"endBalance\", \"type\": \"uint256\" },\n { \"name\": \"gasLimit\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"sweepCCTP\", \"type\": \"SweepCCTP\" }\n ],\n \"SweepCCTP\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"destinationDomain\", \"type\": \"uint32\" },\n { \"name\": \"destinationMintRecipient\", \"type\": \"bytes32\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"endBalance\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"sweepDepositAccountERC20\", \"type\": \"SweepDepositAccountERC20\" }\n ],\n \"SweepDepositAccountERC20\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"depositor\", \"type\": \"address\" },\n { \"name\": \"recipient\", \"type\": \"address\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"sweepDepositAccount\", \"type\": \"SweepDepositAccount\" }\n ],\n \"SweepDepositAccount\": [\n { \"name\": \"depositor\", \"type\": \"address\" },\n { \"name\": \"recipient\", \"type\": \"address\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"sweepERC20\", \"type\": \"SweepERC20\" }\n ],\n \"SweepERC20\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"target\", \"type\": \"address\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"endBalance\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n {\n \"name\": \"sweepSkipCCTPDepositAccount\",\n \"type\": \"SweepSkipCCTPDepositAccount\"\n }\n ],\n \"SweepSkipCCTPDepositAccount\": [\n { \"name\": \"depositor\", \"type\": \"address\" },\n { \"name\": \"destinationDomain\", \"type\": \"uint32\" },\n { \"name\": \"destinationMintRecipient\", \"type\": \"bytes32\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"sweepUniswapV3\", \"type\": \"SweepUniswapV3\" }\n ],\n \"SweepUniswapV3\": [\n { \"name\": \"recipient\", \"type\": \"address\" },\n { \"name\": \"tokenIn\", \"type\": \"address\" },\n { \"name\": \"tokenOut\", \"type\": \"address\" },\n { \"name\": \"feeTier\", \"type\": \"uint24\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"endBalance\", \"type\": \"uint256\" },\n { \"name\": \"floorAmountOut\", \"type\": \"uint256\" },\n { \"name\": \"meanPriceLookBack\", \"type\": \"uint32\" },\n { \"name\": \"maxPriceDeviationBPS\", \"type\": \"uint32\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"sweep\", \"type\": \"Sweep\" }\n ],\n \"Sweep\": [\n { \"name\": \"target\", \"type\": \"address\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"endBalance\", \"type\": \"uint256\" },\n { \"name\": \"gasLimit\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"transferERC20\", \"type\": \"TransferERC20\" }\n ],\n \"TransferERC20\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"target\", \"type\": \"address\" },\n { \"name\": \"value\", \"type\": \"uint256\" },\n { \"name\": \"schedule\", \"type\": \"Schedule\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Schedule\": [\n { \"name\": \"startAt\", \"type\": \"uint256\" },\n { \"name\": \"startBy\", \"type\": \"uint256\" },\n { \"name\": \"interval\", \"type\": \"uint256\" },\n { \"name\": \"timeout\", \"type\": \"uint256\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"transfer\", \"type\": \"Transfer\" }\n ],\n \"Transfer\": [\n { \"name\": \"target\", \"type\": \"address\" },\n { \"name\": \"value\", \"type\": \"uint256\" },\n { \"name\": \"gasLimit\", \"type\": \"uint256\" },\n { \"name\": \"schedule\", \"type\": \"Schedule\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Schedule\": [\n { \"name\": \"startAt\", \"type\": \"uint256\" },\n { \"name\": \"startBy\", \"type\": \"uint256\" },\n { \"name\": \"interval\", \"type\": \"uint256\" },\n { \"name\": \"timeout\", \"type\": \"uint256\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"uniswapV3ExactInput\", \"type\": \"UniswapV3ExactInput\" }\n ],\n \"UniswapV3ExactInput\": [\n { \"name\": \"recipient\", \"type\": \"address\" },\n { \"name\": \"tokenIn\", \"type\": \"address\" },\n { \"name\": \"tokenOut\", \"type\": \"address\" },\n { \"name\": \"feeTier\", \"type\": \"uint24\" },\n { \"name\": \"amountIn\", \"type\": \"uint256\" },\n { \"name\": \"floorAmountOut\", \"type\": \"uint256\" },\n { \"name\": \"meanPriceLookBack\", \"type\": \"uint32\" },\n { \"name\": \"maxPriceDeviationBPS\", \"type\": \"uint32\" },\n { \"name\": \"schedule\", \"type\": \"Schedule\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Schedule\": [\n { \"name\": \"startAt\", \"type\": \"uint256\" },\n { \"name\": \"startBy\", \"type\": \"uint256\" },\n { \"name\": \"interval\", \"type\": \"uint256\" },\n { \"name\": \"timeout\", \"type\": \"uint256\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "import type { Address } from \"@otim/utils/schemas\";\n\nimport deactivateInstructionTypes from \"./contracts/schemas/eip-712/actions/deactivate-instruction.json\";\nimport refuelERC20Types from \"./contracts/schemas/eip-712/actions/refuel-erc20.json\";\nimport refuelTypes from \"./contracts/schemas/eip-712/actions/refuel.json\";\nimport sweepCCTPTypes from \"./contracts/schemas/eip-712/actions/sweep-cctp.json\";\nimport sweepDepositAccountERC20Types from \"./contracts/schemas/eip-712/actions/sweep-deposit-account-erc20.json\";\nimport sweepDepositAccountTypes from \"./contracts/schemas/eip-712/actions/sweep-deposit-account.json\";\nimport sweepERC20Types from \"./contracts/schemas/eip-712/actions/sweep-erc20.json\";\nimport sweepSkipCCTPDepositAccountTypes from \"./contracts/schemas/eip-712/actions/sweep-skip-cctp-deposit-account.json\";\nimport sweepUniswapV3Types from \"./contracts/schemas/eip-712/actions/sweep-uniswap-v3.json\";\nimport sweepTypes from \"./contracts/schemas/eip-712/actions/sweep.json\";\nimport transferERC20Types from \"./contracts/schemas/eip-712/actions/transfer-erc20.json\";\nimport transferTypes from \"./contracts/schemas/eip-712/actions/transfer.json\";\nimport uniswapV3ExactInputTypes from \"./contracts/schemas/eip-712/actions/uniswap-v3-exact-input.json\";\n\n/**\n * EIP-712 types structure for instruction signatures.\n */\nexport interface EIP712Types {\n types: {\n [key: string]: Array<{ name: string; type: string }>;\n Instruction: Array<{ name: string; type: string }>;\n };\n}\n\n/**\n * Map of instruction actions to their EIP-712 type definitions.\n * Used for creating typed data structures for instruction signatures.\n *\n * @example\n * ```ts\n * const types = eip712TypesMap['transfer'];\n * ```\n */\nexport const eip712TypesMap = {\n refuel: refuelTypes,\n refuelERC20: refuelERC20Types,\n transfer: transferTypes,\n transferERC20: transferERC20Types,\n uniswapV3ExactInput: uniswapV3ExactInputTypes,\n sweep: sweepTypes,\n sweepERC20: sweepERC20Types,\n sweepCCTP: sweepCCTPTypes,\n sweepUniswapV3: sweepUniswapV3Types,\n sweepDepositAccount: sweepDepositAccountTypes,\n sweepDepositAccountERC20: sweepDepositAccountERC20Types,\n sweepSkipCCTPDepositAccount: sweepSkipCCTPDepositAccountTypes,\n deactivateInstruction: deactivateInstructionTypes,\n} as const satisfies Partial<Record<string, EIP712Types>>;\n\n/**\n * Base instruction build payload containing fields common to all instructions.\n */\nexport interface BaseInstructionBuildPayload {\n // Account address that will execute the instruction\n address: Address;\n // Chain ID where the instruction will be executed\n chainId: number;\n // Maximum number of times the instruction can be executed (0 = unlimited)\n maxExecutions: number;\n // Optional salt for uniqueness\n salt?: number;\n // Fee configuration for instruction execution\n fee: {\n executionFee: string;\n maxBaseFeePerGas: string;\n maxPriorityFeePerGas: string;\n token: Address;\n };\n}\n\n/**\n * Extended base payload for instructions that support scheduling.\n * Includes all base fields plus schedule configuration.\n */\nexport interface ScheduledInstructionBuildPayload\n extends BaseInstructionBuildPayload {\n // Schedule configuration for when and how often the instruction runs\n schedule: {\n // Unix timestamp (seconds) when instruction should start (0 = immediate)\n startAt: number;\n // Unix timestamp (seconds) by which instruction must start (0 = no deadline)\n startBy: number;\n // Interval (seconds) between executions\n interval: number;\n // Maximum latency (seconds) allowed for scheduled execution (0 = no limit)\n timeout: number;\n };\n}\n\n/**\n * Extended payload for instructions that support an optional token parameter.\n * This is typically used for ERC20 variants of actions.\n */\nexport interface TokenInstructionPayload {\n // Optional token address (if not provided, uses native currency)\n token?: Address;\n}\n\n/**\n * Extended payload for instructions that support gas limit configuration.\n * Used by actions like transfer and refuel.\n */\nexport interface GasLimitConfigurablePayload {\n // Optional gas limit for the action (0 or undefined = auto)\n gasLimit?: number;\n}\n", "import type { EIP712Types } from \"@otim/utils/instructions\";\nimport type { AbiParameter } from \"abitype\";\n\nimport { eip712TypesMap } from \"@otim/utils/instructions\";\n\nconst feeAbiComponent = {\n name: \"fee\",\n type: \"tuple\",\n components: [\n { name: \"token\", type: \"address\" },\n { name: \"maxBaseFeePerGas\", type: \"uint256\" },\n { name: \"maxPriorityFeePerGas\", type: \"uint256\" },\n { name: \"executionFee\", type: \"uint256\" },\n ],\n} as const satisfies AbiParameter;\n\nconst sweepAbi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"target\", type: \"address\" },\n { name: \"threshold\", type: \"uint256\" },\n { name: \"endBalance\", type: \"uint256\" },\n { name: \"gasLimit\", type: \"uint256\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst sweepERC20Abi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"token\", type: \"address\" },\n { name: \"target\", type: \"address\" },\n { name: \"threshold\", type: \"uint256\" },\n { name: \"endBalance\", type: \"uint256\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst sweepCCTPAbi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"token\", type: \"address\" },\n { name: \"destinationDomain\", type: \"uint32\" },\n { name: \"destinationMintRecipient\", type: \"bytes32\" },\n { name: \"threshold\", type: \"uint256\" },\n { name: \"endBalance\", type: \"uint256\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst sweepUniswapV3Abi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"recipient\", type: \"address\" },\n { name: \"tokenIn\", type: \"address\" },\n { name: \"tokenOut\", type: \"address\" },\n { name: \"feeTier\", type: \"uint24\" },\n { name: \"threshold\", type: \"uint256\" },\n { name: \"endBalance\", type: \"uint256\" },\n { name: \"floorAmountOut\", type: \"uint256\" },\n { name: \"meanPriceLookBack\", type: \"uint32\" },\n { name: \"maxPriceDeviationBPS\", type: \"uint32\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst sweepDepositAccountAbi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"depositor\", type: \"address\" },\n { name: \"recipient\", type: \"address\" },\n { name: \"threshold\", type: \"uint256\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst sweepDepositAccountERC20Abi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"token\", type: \"address\" },\n { name: \"depositor\", type: \"address\" },\n { name: \"recipient\", type: \"address\" },\n { name: \"threshold\", type: \"uint256\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst sweepSkipCCTPDepositAccountAbi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"depositor\", type: \"address\" },\n { name: \"destinationDomain\", type: \"uint32\" },\n { name: \"destinationMintRecipient\", type: \"bytes32\" },\n { name: \"threshold\", type: \"uint256\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst actionAbiMap = {\n sweep: sweepAbi,\n sweepERC20: sweepERC20Abi,\n sweepCCTP: sweepCCTPAbi,\n sweepUniswapV3: sweepUniswapV3Abi,\n sweepDepositAccount: sweepDepositAccountAbi,\n sweepDepositAccountERC20: sweepDepositAccountERC20Abi,\n sweepSkipCCTPDepositAccount: sweepSkipCCTPDepositAccountAbi,\n} as const;\n\nexport interface InstructionTypeDefinition {\n abi: readonly AbiParameter[];\n eip712Types: EIP712Types;\n}\n\ntype ActionName = keyof typeof actionAbiMap;\n\nclass InstructionTypeRegistry {\n private registry = new Map<string, InstructionTypeDefinition>();\n\n constructor() {\n this.initializeDefaultTypes();\n }\n\n register(actionName: string, definition: InstructionTypeDefinition): void {\n this.registry.set(actionName, definition);\n }\n\n get(actionName: string): InstructionTypeDefinition {\n const definition = this.registry.get(actionName);\n\n if (!definition) {\n throw this.createUnsupportedTypeError(actionName);\n }\n\n return definition;\n }\n\n has(actionName: string): boolean {\n return this.registry.has(actionName);\n }\n\n getAvailableTypes(): string[] {\n return Array.from(this.registry.keys());\n }\n\n private initializeDefaultTypes(): void {\n const actionNames = Object.keys(actionAbiMap) as ActionName[];\n\n for (const actionName of actionNames) {\n const abi = actionAbiMap[actionName];\n const eip712Types = eip712TypesMap[actionName];\n\n if (abi && eip712Types) {\n this.register(actionName, { abi, eip712Types });\n }\n }\n }\n\n private createUnsupportedTypeError(actionName: string): Error {\n const availableTypes = this.getAvailableTypes().join(\", \");\n return new Error(\n `Unsupported instruction type: ${actionName}. Available: ${availableTypes}`,\n );\n }\n}\n\nexport const instructionRegistry = new InstructionTypeRegistry();\n", "import type { PaymentRequestBuildResponse } from \"@otim/utils/api\";\nimport type { Optional } from \"@otim/utils/helpers\";\n\ninterface InstructionWithActionName {\n actionName?: string;\n}\n\nexport interface PaymentResponseWithActionNames\n extends PaymentRequestBuildResponse {\n completionInstructions: Array<\n PaymentRequestBuildResponse[\"completionInstructions\"][number] &\n InstructionWithActionName\n >;\n instructions: Array<\n PaymentRequestBuildResponse[\"instructions\"][number] &\n InstructionWithActionName\n >;\n}\n\ninterface InstructionWithArguments {\n actionArguments: Record<string, unknown>;\n}\n\ntype ActionNamesMap = Record<number, string>;\n\nexport function addActionNamesToInstructions(\n buildResponse: PaymentRequestBuildResponse,\n actionNames: ActionNamesMap,\n): PaymentResponseWithActionNames {\n const completionInstructionCount =\n buildResponse.completionInstructions.length;\n\n return {\n ...buildResponse,\n completionInstructions: buildResponse.completionInstructions.map(\n (instruction, index) => ({\n ...instruction,\n actionName: actionNames[index],\n }),\n ),\n instructions: buildResponse.instructions.map((instruction, index) => ({\n ...instruction,\n actionName: actionNames[completionInstructionCount + index],\n })),\n };\n}\n\nexport function extractActionNamesMap(\n completionInstructions: InstructionWithArguments[],\n instructions: InstructionWithArguments[] = [],\n): ActionNamesMap {\n const allInstructions = [...completionInstructions, ...instructions];\n\n return allInstructions.reduce<ActionNamesMap>(\n (actionNamesMap, instruction, index) => {\n const actionName = getFirstActionArgumentKey(instruction.actionArguments);\n if (actionName) {\n actionNamesMap[index] = actionName;\n }\n return actionNamesMap;\n },\n {},\n );\n}\n\nfunction getFirstActionArgumentKey(\n actionArguments: Record<string, unknown>,\n): Optional<string> {\n const keys = Object.keys(actionArguments);\n return keys[0];\n}\n", "interface SignatureCountAssertion {\n expected: number;\n received: number;\n}\n\n/**\n * Used to validate the number of signatures in a payment request.\n */\nexport class SignatureValidator {\n static assertExactCount(context: SignatureCountAssertion): void {\n if (context.received !== context.expected) {\n throw new Error(\n `Signature count mismatch: expected ${context.expected}, received ${context.received}`,\n );\n }\n }\n\n static assertMinimumCount(context: SignatureCountAssertion): void {\n if (context.received < context.expected) {\n throw new Error(\n `Insufficient signatures: expected at least ${context.expected}, received ${context.received}`,\n );\n }\n }\n}\n\nexport function assertSignatureCount<T>(\n signatures: T[],\n expectedCount: number,\n): asserts signatures is T[] & { length: typeof expectedCount } {\n SignatureValidator.assertExactCount({\n expected: expectedCount,\n received: signatures.length,\n });\n}\n\nexport function assertMinimumSignatures<T>(\n signatures: T[],\n minimumCount: number,\n): asserts signatures is T[] & { length: number } {\n SignatureValidator.assertMinimumCount({\n expected: minimumCount,\n received: signatures.length,\n });\n}\n", "import type { HexString } from \"../schemas\";\nimport type { ChainTokenConfig } from \"./comprehensive-payment-request\";\n\ninterface Token {\n address: string;\n symbol: string;\n chainId: number;\n decimals: number;\n}\n\nexport function createChainTokenConfigs(tokens: Token[]): ChainTokenConfig[] {\n const tokensByChain = groupTokensByChainId(tokens);\n return convertToChainConfigs(tokensByChain);\n}\n\nfunction groupTokensByChainId(tokens: Token[]): Map<number, Token[]> {\n const grouped = new Map<number, Token[]>();\n\n for (const token of tokens) {\n const chainTokens = grouped.get(token.chainId) ?? [];\n chainTokens.push(token);\n grouped.set(token.chainId, chainTokens);\n }\n\n return grouped;\n}\n\nfunction convertToChainConfigs(\n tokensByChain: Map<number, Token[]>,\n): ChainTokenConfig[] {\n return Array.from(tokensByChain.entries()).map(([chainId, tokens]) => ({\n chainId,\n tokens: tokens.map((token) => ({\n symbol: token.symbol,\n address: token.address as HexString,\n decimals: token.decimals,\n })),\n }));\n}\n", "import type { Nullable, Nullish } from \"@otim/utils/helpers\";\nimport type { Address } from \"@otim/utils/schemas\";\n\nimport { isStablecoin } from \"@otim/utils/chains\";\nimport { DEFAULT_ADDRESS } from \"@otim/utils/helpers\";\n\ninterface Token {\n symbol: string;\n address: string;\n}\n\n/**\n * Checks if a token is the native blockchain token (ETH)\n */\nexport function isNativeToken<T extends Pick<Token, \"symbol\" | \"address\">>(\n token: Nullish<T>,\n): boolean {\n if (!token) {\n return false;\n }\n\n return (\n token.symbol === \"ETH\" ||\n token.address.toLowerCase() === DEFAULT_ADDRESS.toLowerCase()\n );\n}\n\ninterface ResolveStablecoinParams<T extends Token> {\n preferredToken: Nullish<T>;\n getStablecoinBySymbol: (symbol: string) => Nullable<T>;\n}\n\n/**\n * Resolves the stablecoin to use for a payment request.\n * Falls back to USDC or USDT if the preferred token is invalid.\n */\nexport function resolvePreferredStablecoin<T extends Token>({\n preferredToken,\n getStablecoinBySymbol,\n}: ResolveStablecoinParams<T>): Nullable<T> {\n const stablecoin = getValidStablecoin(preferredToken);\n if (stablecoin) {\n return stablecoin;\n }\n\n return getDefaultStablecoin(getStablecoinBySymbol);\n}\n\n/**\n * Validates that a token is a non-native stablecoin\n */\nfunction getValidStablecoin<T extends Token>(token: Nullish<T>): Nullable<T> {\n if (!token || isNativeToken(token) || !isStablecoin(token.symbol)) {\n return null;\n }\n\n return token;\n}\n\n/**\n * Returns a default stablecoin with priority: USDC > USDT\n */\nfunction getDefaultStablecoin<T extends Token>(\n getStablecoinBySymbol: (symbol: string) => Nullable<T>,\n): Nullable<T> {\n const usdc = getStablecoinBySymbol(\"USDC\");\n if (usdc) {\n return usdc;\n }\n\n const usdt = getStablecoinBySymbol(\"USDT\");\n if (usdt) {\n return usdt;\n }\n\n return null;\n}\n\n/**\n * Creates a unique identifier for a token by combining chain ID and address\n */\nexport function createTokenIdentifier(\n chainId: number,\n tokenAddress: Address,\n): string {\n return `${chainId}:${tokenAddress}`;\n}\n", "/**\n * Payment Metadata Builder\n *\n * Handles metadata construction for payment requests with two distinct flows:\n * manual payments (user-entered data) and invoice-based payments (from\n * integrations). Ensures consistent metadata structure across both flows while\n * preventing data conflicts.\n */\n\nimport type { InvoiceMetadata } from \"./payment-metadata\";\nimport type { Nullable } from \"@otim/utils/helpers\";\nimport type { PaymentRequestMetadata } from \"@otim/utils/payments\";\n\nimport { isNumber, isValidDate } from \"@otim/utils/helpers\";\n\n/**\n * Default currency for payments\n */\nconst DEFAULT_CURRENCY = \"USD\" as const;\n\n/**\n * Configuration for manual payment request metadata\n */\nexport interface BuildPaymentMetadataParams {\n tokenSymbol: string;\n note?: string;\n dueDate?: string;\n amountInUSD?: Nullable<number>;\n /**\n * Prevents amount/currency conflicts when invoice metadata will be merged\n * later.\n */\n hasInvoiceMetadata?: boolean;\n fromAccountAddress?: string;\n}\n\n/**\n * Configuration for merging invoice data with payment metadata\n */\nexport interface BuildInvoiceMetadataParams {\n invoiceMetadata: InvoiceMetadata;\n baseMetadata: PaymentRequestMetadata;\n}\n\n/**\n * Validates that a value is a safe, finite number suitable for monetary\n * amounts. Excludes NaN and Infinity which could cause calculation errors\n * downstream.\n */\nfunction isValidAmount(value: unknown): value is number {\n return isNumber(value) && Number.isFinite(value);\n}\n\n/**\n * Constructs payment metadata for manually created payment requests.\n * Conditionally includes amount/currency to avoid conflicts when invoice data\n * will be merged later (invoice data should be the source of truth for amounts).\n */\nexport function buildPaymentMetadata(\n params: BuildPaymentMetadataParams,\n): PaymentRequestMetadata {\n const {\n note,\n tokenSymbol,\n dueDate,\n amountInUSD,\n hasInvoiceMetadata = false,\n fromAccountAddress,\n } = params;\n\n const metadata: PaymentRequestMetadata = {\n token: tokenSymbol,\n };\n\n /**\n * Exclude amount/currency when invoice metadata exists to prevent\n * discrepancies between manually entered and invoice-sourced amounts\n */\n if (!hasInvoiceMetadata) {\n if (isValidAmount(amountInUSD)) {\n metadata.amountDue = amountInUSD.toFixed(2);\n }\n metadata.currency = DEFAULT_CURRENCY;\n }\n\n if (dueDate) {\n metadata.dueDate = dueDate;\n }\n\n if (note) {\n metadata.note = note;\n }\n\n if (fromAccountAddress) {\n metadata.fromAccountAddress = fromAccountAddress;\n }\n\n return metadata;\n}\n\n/**\n * Merges invoice data from external integrations (Stripe, QuickBooks,\n * Bill.com, Clio) with base payment metadata. Invoice fields override manual\n * entries to ensure accuracy and maintain audit trail through source/invoiceId\n * tracking.\n */\nexport function buildInvoiceMetadata(\n params: BuildInvoiceMetadataParams,\n): PaymentRequestMetadata {\n const { invoiceMetadata, baseMetadata } = params;\n\n return {\n ...baseMetadata,\n /**\n * Invoice amounts/dates are authoritative - they override any manually\n * entered values to prevent sync issues with external systems\n */\n amountDue: Number(invoiceMetadata.amount).toFixed(2),\n currency: invoiceMetadata.currency,\n dueDate: invoiceMetadata.dueDate,\n /** Preserve user's manual note if invoice doesn't provide one */\n note: invoiceMetadata.description ?? baseMetadata.note,\n /** Track integration source for reconciliation and debugging */\n source: invoiceMetadata.source,\n invoiceId: invoiceMetadata.invoiceId,\n invoiceNumber: invoiceMetadata.invoiceNumber,\n };\n}\n\n/**\n * Validates metadata structure before sending to backend API.\n * Catches type mismatches and invalid values that would cause payment\n * creation failures or blockchain transaction errors.\n */\nexport function validatePaymentMetadata(metadata: PaymentRequestMetadata): {\n isValid: boolean;\n errors: string[];\n} {\n const errors: string[] = [];\n\n /** Token symbol is required for all payment types (stablecoin or native) */\n const token = metadata[\"token\"];\n if (!token || typeof token !== \"string\") {\n errors.push(\"Token symbol is required\");\n }\n\n /**\n * Amount validation handles both string and number types since\n * different integrations may provide amounts in different formats\n */\n const amountDue = metadata[\"amountDue\"];\n if (amountDue !== undefined && amountDue !== null) {\n const amount =\n typeof amountDue === \"string\" ? parseFloat(amountDue) : Number(amountDue);\n if (!isValidAmount(amount) || amount < 0) {\n errors.push(\"Amount must be a valid positive number\");\n }\n }\n\n /**\n * Due dates must be valid ISO strings for consistent timezone handling\n * and proper comparison in payment status calculations\n */\n const dueDate = metadata[\"dueDate\"];\n if (dueDate !== undefined && dueDate !== null) {\n if (typeof dueDate !== \"string\") {\n errors.push(\"Due date must be a string\");\n } else {\n const date = new Date(dueDate);\n if (!isValidDate(date)) {\n errors.push(\"Due date must be a valid ISO date string\");\n }\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { Address, HexString } from \"@otim/utils/schemas\";\n\nexport const PaymentAction = {\n Sweep: \"sweep\",\n SweepCCTP: \"sweepCCTP\",\n SweepERC20: \"sweepERC20\",\n SweepUniswapV3: \"sweepUniswapV3\",\n} as const;\nexport type PaymentAction = (typeof PaymentAction)[keyof typeof PaymentAction];\nexport interface BaseEphemeralInstructionPayload {\n chainId: number;\n maxExecutions: number;\n fee: {\n maxBaseFeePerGas: HexString;\n maxPriorityFeePerGas: HexString;\n token: Address;\n };\n}\n\nexport interface TokenSpec {\n address: Address;\n decimals: number;\n symbol: string;\n}\n\nexport interface PaymentRequestMetadata extends Record<string, unknown> {\n payer?: { name?: string; address?: Address };\n}\n\n/**\n * Uniswap V3 fee tiers. Used to specify the fee tier for a Uniswap V3 swap.\n * @see https://docs.uniswap.org/concepts/protocol/fees\n */\nexport const UniswapV3FeeTier = {\n Lowest: \"100\",\n Low: \"500\",\n Medium: \"3000\",\n High: \"10000\",\n} as const;\nexport type UniswapV3FeeTier =\n (typeof UniswapV3FeeTier)[keyof typeof UniswapV3FeeTier];\n", "import type { Nullable } from \"@otim/utils/helpers\";\n\nimport {\n arbitrum,\n arbitrumSepolia,\n base,\n baseSepolia,\n mainnet,\n optimism,\n optimismSepolia,\n sepolia,\n} from \"viem/chains\";\n\nexport interface CCTPConfig {\n supportedChainIds: Set<number>;\n isSupported(chainId: number): boolean;\n getDomain(chainId: number): Nullable<number>;\n}\n\n/**\n * List of chains that support CCTP\n * Only includes chains that have confirmed CCTP support from Circle\n * @see https://developers.circle.com/stablecoins/docs/supported-domains\n */\nconst cctpSupportedChains = new Set([\n mainnet.id,\n optimism.id,\n arbitrum.id,\n base.id,\n sepolia.id,\n optimismSepolia.id,\n arbitrumSepolia.id,\n baseSepolia.id,\n]);\n\n/**\n * CCTP Domain Mapping - Maps chain IDs to their Circle CCTP domain identifiers\n * Source: https://developers.circle.com/stablecoins/docs/supported-domains\n *\n * Domain IDs are used by Circle's Cross-Chain Transfer Protocol (CCTP) to\n * identify destination chains when burning and minting USDC across different\n * networks.\n */\nconst cctpDomainMapping: Record<number, number> = {\n [mainnet.id]: 0,\n [optimism.id]: 2,\n [arbitrum.id]: 3,\n [base.id]: 6,\n [sepolia.id]: 0,\n [optimismSepolia.id]: 2,\n [arbitrumSepolia.id]: 3,\n [baseSepolia.id]: 6,\n};\n\nexport class DefaultCCTPConfig implements CCTPConfig {\n supportedChainIds: Set<number>;\n\n constructor() {\n this.supportedChainIds = cctpSupportedChains;\n }\n\n isSupported(chainId: number): boolean {\n return this.supportedChainIds.has(chainId);\n }\n\n getDomain(chainId: number): Nullable<number> {\n return cctpDomainMapping[chainId] ?? null;\n }\n}\n\nexport const defaultCCTPConfig = new DefaultCCTPConfig();\n", "import type { EIP2098Signature, HexString, VRS } from \"@otim/utils/schemas\";\nimport type { Chain } from \"viem\";\n\nimport { isAddressEqual } from \"viem\";\n\nexport const truncateAddress = (address: string): string => {\n if (!address) return \"\";\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n};\n\n/**\n * Ethereum address regex pattern\n * Matches addresses like 0x1234...abcd (40 hex characters after 0x prefix)\n */\nexport const ETHEREUM_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/;\n\n/**\n * Validates if a string is a valid Ethereum address format\n * @param address - The address string to validate\n * @returns true if the address matches the Ethereum address format\n */\nexport const isValidEthereumAddress = (address: string): boolean => {\n return ETHEREUM_ADDRESS_REGEX.test(address);\n};\n\n/**\n * Parses a signature string into its v, r, s components.\n * @param signature - The signature string to parse (must be 0x-prefixed, 132 chars total)\n * @returns VRS object containing v, r, and s values\n */\nexport const parseSignatureToVRS = (signature: string): VRS => {\n if (typeof signature !== \"string\") {\n throw new Error(\"Signature must be a string\");\n }\n\n if (!signature.startsWith(\"0x\")) {\n throw new Error('Signature must start with \"0x\"');\n }\n\n if (signature.length !== 132) {\n throw new Error(\n 'Signature must be 65 bytes (130 hex chars) plus \"0x\" = 132 total length',\n );\n }\n\n const r = signature.slice(2, 66);\n const s = signature.slice(66, 130);\n const vHex = signature.slice(130, 132);\n const v = parseInt(vHex, 16);\n return { v, r: `0x${r}`, s: `0x${s}` };\n};\n\n/**\n * Checks if a v value is valid according to EIP-155.\n */\nexport const isValidV = (v: number): boolean => {\n return v === 0 || v === 1 || v === 27 || v === 28 || v >= 35;\n};\n\n/**\n * Normalizes v value for EIP-155 compliance.\n */\nexport const normalizeV = (v: number) => {\n if (!isValidV(v)) return 0;\n\n const cmp = v <= 1 ? 1 : 0;\n const result = v % 2 === cmp;\n\n return Number(result) % 2;\n};\n\n/**\n * Creates an EIP-2098 compact signature from VRS components.\n * @param vrs - The VRS signature components\n * @returns EIP2098Signature object with yParity, r, and s\n */\nexport const createEIP2098Signature = (vrs: VRS): EIP2098Signature => {\n const v = vrs.v;\n const r = vrs.r;\n const s = vrs.s;\n\n return { yParity: normalizeV(v), r, s };\n};\n\nexport const getChainRpcUrl = (\n chainId: number,\n chains: readonly [Chain, ...Chain[]],\n) => {\n const chain = chains.find((chain) => chain.id === chainId);\n return chain?.rpcUrls.default;\n};\n\nexport const DEFAULT_ADDRESS = \"0x0000000000000000000000000000000000000000\";\n\nexport const isNullAddress = (address: HexString) => {\n return isAddressEqual(address, DEFAULT_ADDRESS);\n};\n", "import z from \"zod\";\n\nimport { logger } from \"./logger\";\n\ntype Locale = \"en\" | \"es\";\n\ntype FormatDateFunc<T> = (date: Date) => T;\n\nexport const iso8601DateSchema = z\n .string()\n .regex(\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$/,\n \"Must be a valid ISO 8601 date format (e.g., 2024-12-31T23:59:59.000Z)\",\n );\n\nexport const TimeUnit = {\n Day: \"day\",\n Month: \"month\",\n Year: \"year\",\n} as const;\n\nexport type TimeUnit = (typeof TimeUnit)[keyof typeof TimeUnit];\n\nconst units = {\n [TimeUnit.Day]: {\n one: \"day\",\n other: \"days\",\n },\n [TimeUnit.Month]: {\n one: \"month\",\n other: \"months\",\n },\n [TimeUnit.Year]: {\n one: \"year\",\n other: \"years\",\n },\n} as const;\n\nconst formatDateAsUSStandard = (\n date: Date,\n opts?: Intl.DateTimeFormatOptions,\n) =>\n date.toLocaleString(\"en-US\", {\n month: \"2-digit\",\n day: \"2-digit\",\n year: \"numeric\",\n ...opts,\n });\n\nexport const formatDateAsISO = (date: Date) => date.toISOString();\n\nconst formatFullDate = (date: Date): string => {\n const options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"long\",\n day: \"2-digit\",\n timeZone: \"UTC\",\n };\n return new Intl.DateTimeFormat(\"en-US\", options).format(date);\n};\n\nconst formatTime = (date: Date): string => {\n return date.toLocaleTimeString(\"en-US\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n timeZone: \"UTC\",\n timeZoneName: \"short\",\n });\n};\n\nconst formatDateTime = (date: Date): string => {\n const dateOptions: Intl.DateTimeFormatOptions = {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n timeZone: \"UTC\",\n };\n const timeOptions: Intl.DateTimeFormatOptions = {\n hour: \"2-digit\",\n minute: \"2-digit\",\n timeZone: \"UTC\",\n };\n\n const formattedDate = new Intl.DateTimeFormat(\"en-US\", dateOptions).format(\n date,\n );\n const formattedTime = new Intl.DateTimeFormat(\"en-US\", timeOptions).format(\n date,\n );\n\n return `${formattedDate} at ${formattedTime}`;\n};\n\n/**\n * Formats a date in long format (e.g., \"June 19, 2025\")\n * @param date - Date object to format\n * @returns Formatted date string\n */\nconst formatLongDate = (date: Date): string => {\n const options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n timeZone: \"UTC\",\n };\n return new Intl.DateTimeFormat(\"en-US\", options).format(date);\n};\n\n/**\n * Formats a date with time in long format (e.g., \"June 19, 2025 at 07:00 AM\")\n * @param date - Date object to format\n * @returns Formatted date and time string\n */\nconst formatLongDateTime = (date: Date): string => {\n const dateOptions: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n timeZone: \"UTC\",\n };\n const timeOptions: Intl.DateTimeFormatOptions = {\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: true,\n timeZone: \"UTC\",\n };\n\n const formattedDate = new Intl.DateTimeFormat(\"en-US\", dateOptions).format(\n date,\n );\n const formattedTime = new Intl.DateTimeFormat(\"en-US\", timeOptions)\n .format(date)\n .toLowerCase();\n\n return `${formattedDate} at ${formattedTime}`;\n};\n\nconst formatToShortDate = (dateString: string | Date) => {\n const date =\n typeof dateString === \"string\" ? new Date(dateString) : dateString;\n\n if (isNaN(date.getTime())) {\n return \"Jan 1\";\n }\n\n return date.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n timeZone: \"UTC\",\n });\n};\n\nconst formatToShortDateWithYear = (dateString: string | Date) => {\n const date =\n typeof dateString === \"string\" ? new Date(dateString) : dateString;\n\n if (isNaN(date.getTime())) {\n return \"Unknown\";\n }\n\n return date.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n timeZone: \"UTC\",\n });\n};\n\nexport const formatToJustDate = (dateString: string) => {\n const date = new Date(dateString);\n\n if (isNaN(date.getTime())) {\n return \"1\";\n }\n\n return date.getUTCDate().toString();\n};\n\nexport const formatDateToYYYYMMDD = (date: Date) => {\n return new Intl.DateTimeFormat(\"en-CA\", {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n }).format(date);\n};\n\nconst isDateInvalid = (date: Date) => {\n return date.toString() === \"Invalid Date\";\n};\n\n/**\n * Validates if a date is valid (opposite of isDateInvalid)\n * Checks both the Date object validity and the timestamp\n */\nconst isValidDate = (date: Date): boolean => {\n return !isDateInvalid(date) && !isNaN(date.getTime());\n};\n\nconst isDateEpoc = (date: Date) => {\n return date.getTime() <= 0;\n};\n\nconst isDateInRange = (arg: unknown): boolean => {\n if (typeof arg !== \"string\") {\n return false;\n }\n\n const date = new Date(arg);\n const startDate = new Date(\"1800-01-01T00:00:00.000Z\");\n const endDate = new Date(\"2999-12-31T23:59:59.999Z\");\n\n return date >= startDate && date <= endDate;\n};\n\nconst isDateInPast = (input: string | number | Date): boolean => {\n let date: Date;\n if (input instanceof Date) {\n date = input;\n } else if (typeof input === \"number\") {\n const ms = input < 1e12 ? input * 1000 : input;\n date = new Date(ms);\n } else {\n date = new Date(input);\n }\n\n if (isNaN(date.getTime())) {\n return false;\n }\n\n return date.getTime() < Date.now();\n};\n\nconst isSameDate = (dateA: Date, dateB: Date) => {\n return (\n dateA.getFullYear() === dateB.getFullYear() &&\n dateA.getMonth() === dateB.getMonth() &&\n dateA.getDate() === dateB.getDate()\n );\n};\n\nconst getPluralizedUnit = (\n unit: keyof typeof units,\n count: number,\n locale: Locale = \"en\",\n) => {\n const pluralRules = new Intl.PluralRules(locale, {\n type: \"cardinal\",\n });\n const pluralCategory = pluralRules.select(count);\n\n if (pluralCategory === \"one\" || pluralCategory === \"other\") {\n return `${count} ${units[unit][pluralCategory]}`;\n }\n\n return `${count} ${units[unit].other}`;\n};\n\nconst getRelativeDateDescription = (\n targetDate: Date,\n locale: Locale = \"en\",\n) => {\n const currentDate = new Date();\n\n const oneDay = 1000 * 60 * 60 * 24;\n const oneMonth = oneDay * 30;\n const oneYear = oneDay * 365;\n\n const diffInMilliseconds = targetDate.getTime() - currentDate.getTime();\n const diffInDays = Math.round(diffInMilliseconds / oneDay);\n const diffInMonths = Math.round(diffInMilliseconds / oneMonth);\n const diffInYears = Math.round(diffInMilliseconds / oneYear);\n\n if (Math.abs(diffInYears) >= 1) {\n return getPluralizedUnit(\"year\", Math.abs(diffInYears), locale);\n }\n\n if (Math.abs(diffInMonths) >= 1) {\n return getPluralizedUnit(\"month\", Math.abs(diffInMonths), locale);\n }\n\n return getPluralizedUnit(\"day\", Math.abs(diffInDays), locale);\n};\n\n/**\n * Safely formats a date with validation and fallback support\n * @param date - String or Date to format\n * @param formatter - Function that formats the Date object\n * @param fallback - Value to return if date is invalid\n * @returns Formatted string or fallback value\n */\nconst safeFormatDate = <T = string>(\n date: string | Date,\n formatter: FormatDateFunc<T>,\n fallback: T,\n): T => {\n const dateObj = typeof date === \"string\" ? new Date(date) : date;\n\n if (!isValidDate(dateObj)) {\n return fallback;\n }\n\n try {\n return formatter(dateObj);\n } catch (error) {\n logger.logError(error, {\n context: safeFormatDate.name,\n });\n return fallback;\n }\n};\n\nconst parseDateTime = (dateInput: string, timeInput?: string) => {\n const dateRegex = /^(\\d{1,2})\\/(\\d{1,2})\\/(\\d{4})$/;\n const timeRegex = /^(\\d{1,2}):(\\d{2})(?::(\\d{2}))?\\s*(AM|PM|am|pm)?$/;\n\n const dateMatch = dateRegex.exec(dateInput);\n if (!dateMatch) {\n return undefined;\n }\n\n const month = parseInt(dateMatch[1]!, 10) - 1;\n const day = parseInt(dateMatch[2]!, 10);\n const year = parseInt(dateMatch[3]!, 10);\n\n let hours = 0;\n let minutes = 0;\n let seconds = 0;\n\n if (timeInput) {\n timeInput = timeInput.replace(/\\u00A0/g, \" \").trim();\n\n const timeMatch = timeRegex.exec(timeInput);\n if (!timeMatch) {\n return undefined;\n }\n\n hours = parseInt(timeMatch[1]!, 10);\n minutes = parseInt(timeMatch[2]!, 10);\n seconds = timeMatch[3] ? parseInt(timeMatch[3], 10) : 0;\n const meridiem = timeMatch[4] ? timeMatch[4].toUpperCase() : null;\n\n if (meridiem === \"PM\" && hours < 12) {\n hours += 12;\n } else if (meridiem === \"AM\" && hours === 12) {\n hours = 0;\n }\n }\n\n const date = new Date(Date.UTC(year, month, day, hours, minutes, seconds));\n if (isNaN(date.getTime())) {\n return undefined;\n }\n\n return date;\n};\n\nconst validateIso8601Date = (dueDate: string): void => {\n const result = iso8601DateSchema.safeParse(dueDate);\n if (!result.success) {\n const errorMessage =\n result.error.issues[0]?.message || \"Invalid ISO 8601 format\";\n throw new Error(`Invalid due date format: ${errorMessage}`);\n }\n};\n\nexport {\n formatDateAsUSStandard,\n formatToShortDate,\n formatToShortDateWithYear,\n formatFullDate,\n formatTime,\n formatDateTime,\n formatLongDate,\n formatLongDateTime,\n getPluralizedUnit,\n getRelativeDateDescription,\n isDateInvalid,\n isValidDate,\n validateIso8601Date,\n isDateEpoc,\n isDateInRange,\n isDateInPast,\n isSameDate,\n safeFormatDate,\n parseDateTime,\n};\nexport type { FormatDateFunc };\n", "import type { z, ZodObject } from \"zod\";\n\nexport type Nullable<T> = T | null;\nexport type Nullish<T> = T | null | undefined;\nexport type Optional<T> = T | undefined;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- any is ok\nexport type Any = any;\n\nexport type NumberOrString = number | string;\n\nexport type OverrideProps<T, TOverridden> = Omit<T, keyof TOverridden> &\n TOverridden;\n\nexport type NonEmptyArray<T> = [T, ...T[]];\n\nexport interface DataRecord {\n [value: string]: Nullish<DataRecord | string | number | boolean>;\n}\n\nexport interface Input<T> {\n input: T;\n}\n\nexport type ZodCustom<Values extends object> = ZodObject<{\n [P in keyof Values]: z.ZodType<Values[P]>;\n}>;\n\nexport const isError = (value: unknown): value is Error =>\n value instanceof Error;\n\nexport const isFunction = (\n value: unknown,\n): value is (...args: unknown[]) => unknown => typeof value === \"function\";\n\nexport const isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nexport const isNumber = (value: unknown): value is number =>\n typeof value === \"number\";\n\nexport const isString = (value: unknown): value is string =>\n typeof value === \"string\";\n\nexport const isUndefined = (value: unknown): value is undefined =>\n typeof value === \"undefined\";\n\nexport const isBoolean = (value: unknown): value is boolean =>\n typeof value === \"boolean\";\n\n/**\n * Safely extracts a string from an unknown value.\n * @param value - The value to extract from\n * @param fallback - Optional fallback value if extraction fails\n * @returns The extracted string or fallback/undefined\n */\nexport const extractString = (\n value: unknown,\n fallback?: string,\n): Optional<string> => {\n return isString(value) ? value : fallback;\n};\n\n/**\n * Safely extracts a number from an unknown value.\n * Handles both number and string representations.\n * @param value - The value to extract from\n * @returns The extracted number or undefined\n */\nexport const extractNumber = (value: unknown): Optional<number> => {\n if (isNumber(value)) {\n return value;\n }\n\n if (isString(value)) {\n const parsed = Number.parseFloat(value);\n return Number.isNaN(parsed) ? undefined : parsed;\n }\n\n return undefined;\n};\n", "/**\n * List of supported stablecoin symbols\n */\nconst stablecoinSymbols = [\"USDC\", \"USDT\"] as const;\n\n/**\n * Checks if a token symbol is a stablecoin\n * @param symbol - Token symbol to check (e.g., \"USDC\", \"ETH\")\n * @returns true if the symbol is a recognized stablecoin\n */\nexport function isStablecoin(symbol: string | string[]): boolean {\n if (typeof symbol === \"string\") {\n return stablecoinSymbols.includes(\n symbol as (typeof stablecoinSymbols)[number],\n );\n }\n\n return symbol.every((s) =>\n stablecoinSymbols.includes(s as (typeof stablecoinSymbols)[number]),\n );\n}\n", "import { isStablecoin } from \"@otim/utils/chains\";\n\nimport { UniswapV3FeeTier } from \"../types\";\n\n/**\n * Determines the recommended Uniswap V3 fee tier for a token pair\n *\n * Stable pairs (USDC/USDT swaps) use the Low fee tier (0.05%) since price\n * volatility is minimal. All other pairs use the Medium fee tier (0.3%) to\n * account for higher price volatility\n *\n * @param tokenIn - Symbol of the input token (e.g., \"USDC\", \"USDT\")\n * @param tokenOut - Symbol of the output token (e.g., \"USDC\", \"USDT\")\n * @returns The recommended Uniswap V3 fee tier for the swap\n */\nexport function getRecommendedFeeTier(\n tokenIn: string,\n tokenOut: string,\n): UniswapV3FeeTier {\n if (isStablecoin([tokenIn, tokenOut])) {\n return UniswapV3FeeTier.Low;\n }\n\n return UniswapV3FeeTier.Medium;\n}\n", "import type { PaymentRequestMetadata } from \"./types\";\nimport type { PaymentRequestBuildRequest } from \"@otim/utils/api\";\nimport type { Nullable } from \"@otim/utils/helpers\";\nimport type { Address, HexString } from \"@otim/utils/schemas\";\n\nimport { DEFAULT_ADDRESS } from \"@otim/utils/helpers\";\n\nexport interface EphemeralInstructionSpec {\n chainId: number;\n salt?: number;\n maxExecutions: number;\n actionArguments: Record<string, unknown>;\n setEphemeralTarget?: boolean;\n}\n\nexport interface BuildPaymentRequestParams {\n payerAddress?: Nullable<Address>;\n completionInstructions: EphemeralInstructionSpec[];\n instructions?: EphemeralInstructionSpec[];\n metadata?: PaymentRequestMetadata;\n maxRuns?: number;\n}\n\ninterface ProcessedInstruction {\n chainId: number;\n salt: number;\n maxExecutions: number;\n actionArguments: Record<string, unknown>;\n setEphemeralTarget: boolean;\n}\n\nexport interface FeeConfig {\n executionFee: number;\n maxBaseFeePerGas: `0x${string}`;\n maxPriorityFeePerGas: `0x${string}`;\n token: Address;\n}\n\nconst DEFAULT_SET_EPHEMERAL_TARGET = true;\n\nexport function createPaymentRequestBuildPayload(\n params: BuildPaymentRequestParams,\n): PaymentRequestBuildRequest {\n const {\n payerAddress = null,\n completionInstructions,\n instructions = [],\n metadata = {},\n maxRuns,\n } = params;\n\n return {\n payerAddress,\n completionInstructions: completionInstructions.map(processInstruction),\n instructions: instructions.map(processInstruction),\n metadata,\n maxRuns,\n };\n}\n\nfunction processInstruction(\n spec: EphemeralInstructionSpec,\n): ProcessedInstruction {\n return {\n chainId: spec.chainId,\n salt: spec.salt ?? generateRandomSalt(),\n maxExecutions: spec.maxExecutions,\n actionArguments: spec.actionArguments,\n setEphemeralTarget: spec.setEphemeralTarget ?? DEFAULT_SET_EPHEMERAL_TARGET,\n };\n}\n\nfunction generateRandomSalt(): number {\n return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);\n}\n\nexport function createDefaultFee(\n executionFee = 0,\n maxBaseFeePerGas: HexString = \"0x0\",\n maxPriorityFeePerGas: HexString = \"0x0\",\n token: Address = DEFAULT_ADDRESS,\n): FeeConfig {\n return {\n token,\n executionFee,\n maxBaseFeePerGas,\n maxPriorityFeePerGas,\n };\n}\n\nexport function createFeeWithToken(\n token?: Address,\n maxPriorityFeePerGas?: `0x${string}`,\n): FeeConfig {\n return createDefaultFee(0, \"0x0\", maxPriorityFeePerGas ?? \"0x0\", token);\n}\n", "import type { EphemeralInstructionSpec } from \"./build\";\nimport type { CCTPConfig } from \"./config/cctp\";\nimport type { PaymentRequestMetadata } from \"./types\";\nimport type { PaymentRequestBuildRequest } from \"@otim/utils/api\";\nimport type { Address } from \"@otim/utils/schemas\";\n\nimport { parseUnits, toHex } from \"viem\";\n\nimport { isStablecoin } from \"@otim/utils/chains\";\n\nimport { createSweepCCTPActionArguments } from \"./actions/sweep-cctp\";\nimport { createSweepERC20ActionArguments } from \"./actions/sweep-erc20\";\nimport { createSweepUniswapV3ActionArguments } from \"./actions/sweep-uniswap-v3\";\nimport { createFeeWithToken, createPaymentRequestBuildPayload } from \"./build\";\nimport { defaultCCTPConfig } from \"./config/cctp\";\nimport { getRecommendedFeeTier } from \"./config/tokens\";\n\nexport interface ChainTokenConfig {\n chainId: number;\n tokens: Array<{\n symbol: string;\n address: Address;\n decimals: number;\n }>;\n}\n\nexport interface ComprehensivePaymentRequestParams {\n settlementChainId: number;\n recipient: Address;\n amount: string;\n ephemeralWalletAddress: Address;\n chainTokenConfigs: ChainTokenConfig[];\n payerAddress?: Address | null;\n metadata?: PaymentRequestMetadata;\n feeToken?: Address;\n cctpConfig?: CCTPConfig;\n maxRuns?: number;\n}\n\ninterface SettlementTokenInfo {\n address: Address;\n decimals: number;\n}\n\nconst USDC_SYMBOL = \"USDC\";\nconst USDT_SYMBOL = \"USDT\";\nconst MINIMUM_THRESHOLD = 1n;\nconst UNISWAP_MEAN_PRICE_LOOKBACK = 600;\n\n/**\n * For payment requests, endBalance is always 0 across all instruction types\n * (Sweep, SweepERC20, SweepCCTP, SweepUniswapV3). This ensures all available\n * tokens are swept/bridged/swapped without leaving dust in the ephemeral\n * wallet.\n */\nconst ZERO_BALANCE = 0n;\n\nconst USDT_MAX_PRICE_DEVIATION_BPS = 200;\nconst DEFAULT_MAX_PRICE_DEVIATION_BPS = 500;\n\nconst STABLE_SLIPPAGE_BPS = 1;\nconst NON_STABLE_SLIPPAGE_BPS = 50;\n\nexport function createComprehensivePaymentRequest(\n params: ComprehensivePaymentRequestParams,\n): PaymentRequestBuildRequest {\n const {\n settlementChainId,\n recipient,\n amount,\n ephemeralWalletAddress,\n chainTokenConfigs,\n payerAddress,\n metadata,\n feeToken,\n cctpConfig = defaultCCTPConfig,\n maxRuns = 1,\n } = params;\n\n validateSettlementChainSupport(settlementChainId, cctpConfig);\n\n const settlementConfig = findChainConfig(\n settlementChainId,\n chainTokenConfigs,\n );\n const settlementUSDC = findSettlementUSDC(settlementConfig);\n const threshold = calculateThreshold(amount, settlementUSDC.decimals);\n\n /**\n * For payment requests, we don't charge in-protocol fees, so all fee values\n * are set to zero. This provides slight gas savings by pushing fewer non-zero\n * bytes on-chain.\n */\n const instructionFee = createFeeWithToken(feeToken);\n\n const completionInstructions = createCompletionInstructions(\n settlementChainId,\n settlementUSDC.address,\n recipient,\n threshold,\n instructionFee,\n chainTokenConfigs,\n );\n\n const instructions = createCrossChainInstructions(\n chainTokenConfigs,\n settlementChainId,\n ephemeralWalletAddress,\n instructionFee,\n cctpConfig,\n );\n\n return createPaymentRequestBuildPayload({\n payerAddress,\n completionInstructions,\n instructions,\n metadata,\n maxRuns,\n });\n}\n\nfunction validateSettlementChainSupport(\n chainId: number,\n cctpConfig: CCTPConfig,\n): void {\n if (!cctpConfig.isSupported(chainId)) {\n throw new Error(`Settlement chain ${chainId} does not support CCTP`);\n }\n}\n\nfunction findChainConfig(\n chainId: number,\n configs: ChainTokenConfig[],\n): ChainTokenConfig {\n const config = configs.find((c) => c.chainId === chainId);\n\n if (!config) {\n throw new Error(\n `Settlement chain ${chainId} not found in chain token configs`,\n );\n }\n\n return config;\n}\n\nfunction findSettlementUSDC(\n settlementConfig: ChainTokenConfig,\n): SettlementTokenInfo {\n const usdc = settlementConfig.tokens.find(\n (token) => token.symbol.toUpperCase() === USDC_SYMBOL,\n );\n\n if (!usdc) {\n throw new Error(\n `Settlement chain ${settlementConfig.chainId} does not have USDC configured`,\n );\n }\n\n return {\n address: usdc.address,\n decimals: usdc.decimals,\n };\n}\n\nfunction calculateThreshold(amount: string, decimals: number): `0x${string}` {\n return toHex(parseUnits(amount, decimals));\n}\n\nfunction createCompletionInstructions(\n settlementChainId: number,\n settlementUSDCAddress: Address,\n recipient: Address,\n threshold: `0x${string}`,\n instructionFee: ReturnType<typeof createFeeWithToken>,\n chainTokenConfigs: ChainTokenConfig[],\n): EphemeralInstructionSpec[] {\n const instructions: EphemeralInstructionSpec[] = [];\n\n instructions.push(\n createSettlementSweepInstruction(\n settlementChainId,\n settlementUSDCAddress,\n recipient,\n threshold,\n instructionFee,\n ),\n );\n\n const swapInstructions = createTokenSwapInstructions(\n settlementChainId,\n chainTokenConfigs,\n recipient,\n threshold,\n instructionFee,\n );\n\n instructions.push(...swapInstructions);\n\n return instructions;\n}\n\n/**\n * Creates the final settlement sweep instruction that sends USDC to the\n * recipient. For payment requests, endBalance is always 0 to sweep all\n * available tokens.\n */\nfunction createSettlementSweepInstruction(\n chainId: number,\n tokenAddress: Address,\n recipient: Address,\n threshold: `0x${string}`,\n fee: ReturnType<typeof createFeeWithToken>,\n): EphemeralInstructionSpec {\n return {\n chainId,\n maxExecutions: 0,\n actionArguments: createSweepERC20ActionArguments({\n chainId,\n maxExecutions: 0,\n token: tokenAddress,\n target: recipient,\n threshold,\n endBalance: toHex(ZERO_BALANCE),\n fee,\n }),\n setEphemeralTarget: false,\n };\n}\n\nfunction createTokenSwapInstructions(\n settlementChainId: number,\n chainTokenConfigs: ChainTokenConfig[],\n settlementRecipient: Address,\n threshold: `0x${string}`,\n instructionFee: ReturnType<typeof createFeeWithToken>,\n): EphemeralInstructionSpec[] {\n const swapInstructions: EphemeralInstructionSpec[] = [];\n\n const settlementConfig = chainTokenConfigs.find(\n (c) => c.chainId === settlementChainId,\n );\n\n if (!settlementConfig) {\n return swapInstructions;\n }\n\n const settlementUSDC = settlementConfig.tokens.find(\n (t) => t.symbol.toUpperCase() === USDC_SYMBOL,\n );\n\n if (!settlementUSDC) {\n return swapInstructions;\n }\n\n for (const sourceToken of settlementConfig.tokens) {\n if (sourceToken.symbol.toUpperCase() === USDC_SYMBOL) {\n continue;\n }\n\n const swapInstruction = createSwapInstruction(\n settlementChainId,\n sourceToken,\n settlementUSDC,\n settlementRecipient,\n threshold,\n instructionFee,\n );\n\n swapInstructions.push(swapInstruction);\n }\n\n return swapInstructions;\n}\n\n/**\n * Creates a Uniswap V3 swap instruction as a completion instruction.\n * Uses appropriate slippage tolerance based on token pair (tighter for\n * stables). For payment requests, endBalance is always 0.\n */\nfunction createSwapInstruction(\n chainId: number,\n tokenIn: ChainTokenConfig[\"tokens\"][number],\n tokenOut: ChainTokenConfig[\"tokens\"][number],\n settlementRecipient: Address,\n threshold: `0x${string}`,\n fee: ReturnType<typeof createFeeWithToken>,\n): EphemeralInstructionSpec {\n const { instruction } = createSwapInstructionWithFloor(\n chainId,\n tokenIn,\n tokenOut,\n settlementRecipient,\n threshold,\n fee,\n false,\n );\n return instruction;\n}\n\n/**\n * Creates a Uniswap V3 swap instruction and returns both the instruction\n * and the calculated floorAmountOut for downstream threshold calculations.\n */\nfunction createSwapInstructionWithFloor(\n chainId: number,\n tokenIn: ChainTokenConfig[\"tokens\"][number],\n tokenOut: ChainTokenConfig[\"tokens\"][number],\n recipient: Address,\n threshold: `0x${string}`,\n fee: ReturnType<typeof createFeeWithToken>,\n setEphemeralTarget: boolean,\n): { instruction: EphemeralInstructionSpec; floorAmountOut: bigint } {\n const feeTier = getRecommendedFeeTier(\n tokenIn.symbol.toUpperCase(),\n USDC_SYMBOL,\n );\n\n const isStableToStableSwap = isStablecoin([\n tokenIn.symbol.toUpperCase(),\n tokenOut.symbol.toUpperCase(),\n ]);\n\n const slippageBps = isStableToStableSwap\n ? STABLE_SLIPPAGE_BPS\n : NON_STABLE_SLIPPAGE_BPS;\n\n const maxPriceDeviationBps =\n tokenIn.symbol.toUpperCase() === USDT_SYMBOL\n ? USDT_MAX_PRICE_DEVIATION_BPS\n : DEFAULT_MAX_PRICE_DEVIATION_BPS;\n\n const baseAmount = BigInt(threshold);\n const afterFeeAmount =\n (baseAmount * BigInt(1000000 - Number(feeTier))) / 1000000n;\n const floorAmountOut =\n (afterFeeAmount * BigInt(10000 - slippageBps)) / 10000n;\n\n const instruction: EphemeralInstructionSpec = {\n chainId,\n maxExecutions: 0,\n actionArguments: createSweepUniswapV3ActionArguments({\n chainId,\n maxExecutions: 0,\n recipient,\n tokenIn: tokenIn.address,\n tokenOut: tokenOut.address,\n feeTier,\n threshold,\n endBalance: toHex(ZERO_BALANCE),\n floorAmountOut: toHex(floorAmountOut),\n meanPriceLookBack: UNISWAP_MEAN_PRICE_LOOKBACK,\n maxPriceDeviationBps,\n fee,\n }),\n setEphemeralTarget,\n };\n\n return { instruction, floorAmountOut };\n}\n\n/**\n * Creates swap instructions for non-USDC tokens on non-settlement chains.\n * These swaps send to the ephemeral wallet so the resulting USDC can be\n * bridged.\n *\n * For cross-chain swaps, we set floorAmountOut to 0 because we cannot predict\n * the actual amount that will be swapped. The TWAP oracle provides price\n * manipulation protection at execution time based on the actual swap amount.\n */\nfunction createCrossChainSwapInstructions(\n chainConfig: ChainTokenConfig,\n chainUSDC: ChainTokenConfig[\"tokens\"][number],\n ephemeralWalletAddress: Address,\n instructionFee: ReturnType<typeof createFeeWithToken>,\n): EphemeralInstructionSpec[] {\n const swapInstructions: EphemeralInstructionSpec[] = [];\n\n for (const sourceToken of chainConfig.tokens) {\n if (sourceToken.symbol.toUpperCase() === USDC_SYMBOL) {\n continue;\n }\n\n const feeTier = getRecommendedFeeTier(\n sourceToken.symbol.toUpperCase(),\n USDC_SYMBOL,\n );\n\n const maxPriceDeviationBps =\n sourceToken.symbol.toUpperCase() === USDT_SYMBOL\n ? USDT_MAX_PRICE_DEVIATION_BPS\n : DEFAULT_MAX_PRICE_DEVIATION_BPS;\n\n const instruction: EphemeralInstructionSpec = {\n chainId: chainConfig.chainId,\n maxExecutions: 0,\n actionArguments: createSweepUniswapV3ActionArguments({\n chainId: chainConfig.chainId,\n maxExecutions: 0,\n recipient: ephemeralWalletAddress,\n tokenIn: sourceToken.address,\n tokenOut: chainUSDC.address,\n feeTier,\n threshold: toHex(MINIMUM_THRESHOLD),\n endBalance: toHex(ZERO_BALANCE),\n floorAmountOut: toHex(0n),\n meanPriceLookBack: UNISWAP_MEAN_PRICE_LOOKBACK,\n maxPriceDeviationBps,\n fee: instructionFee,\n }),\n setEphemeralTarget: true,\n };\n\n swapInstructions.push(instruction);\n }\n\n return swapInstructions;\n}\n\nfunction createCrossChainInstructions(\n chainTokenConfigs: ChainTokenConfig[],\n settlementChainId: number,\n ephemeralWalletAddress: Address,\n instructionFee: ReturnType<typeof createFeeWithToken>,\n cctpConfig: CCTPConfig,\n): EphemeralInstructionSpec[] {\n const instructions: EphemeralInstructionSpec[] = [];\n\n for (const chainConfig of chainTokenConfigs) {\n if (chainConfig.chainId === settlementChainId) {\n continue;\n }\n\n const chainUSDC = chainConfig.tokens.find(\n (token) => token.symbol.toUpperCase() === USDC_SYMBOL,\n );\n\n if (!chainUSDC || !cctpConfig.isSupported(chainConfig.chainId)) {\n continue;\n }\n\n const swapInstructions = createCrossChainSwapInstructions(\n chainConfig,\n chainUSDC,\n ephemeralWalletAddress,\n instructionFee,\n );\n\n instructions.push(...swapInstructions);\n\n const bridgeInstruction = createCCTPBridgeInstruction(\n chainConfig.chainId,\n chainUSDC.address,\n settlementChainId,\n ephemeralWalletAddress,\n toHex(MINIMUM_THRESHOLD),\n instructionFee,\n cctpConfig,\n );\n\n instructions.push(bridgeInstruction);\n }\n\n return instructions;\n}\n\n/**\n * Creates a CCTP bridge instruction to move USDC across chains.\n * For payment requests, endBalance is always 0 to bridge all available USDC.\n *\n * The threshold is set to MINIMUM_THRESHOLD (1 wei) so the bridge executes\n * as soon as any USDC is available from upstream swaps, regardless of the\n * actual amount swapped (which is unpredictable).\n */\nfunction createCCTPBridgeInstruction(\n sourceChainId: number,\n tokenAddress: Address,\n destinationChainId: number,\n ephemeralWalletAddress: Address,\n threshold: `0x${string}`,\n fee: ReturnType<typeof createFeeWithToken>,\n cctpConfig: CCTPConfig,\n): EphemeralInstructionSpec {\n return {\n chainId: sourceChainId,\n maxExecutions: 0,\n actionArguments: createSweepCCTPActionArguments({\n chainId: sourceChainId,\n maxExecutions: 0,\n token: tokenAddress,\n destinationChainId,\n destinationMintRecipient: ephemeralWalletAddress,\n threshold,\n endBalance: toHex(ZERO_BALANCE),\n fee,\n cctpConfig,\n }),\n setEphemeralTarget: true,\n };\n}\n", "import type { CCTPConfig } from \"../config/cctp\";\nimport type { BaseEphemeralInstructionPayload } from \"../types\";\nimport type { Address } from \"@otim/utils/schemas\";\n\nimport { pad } from \"viem\";\n\nimport { defaultCCTPConfig } from \"../config/cctp\";\nimport { PaymentAction } from \"../types\";\n\nexport interface SweepCCTPEphemeralPayload\n extends BaseEphemeralInstructionPayload {\n token: Address;\n destinationChainId: number;\n destinationMintRecipient: Address;\n threshold: string;\n endBalance: string;\n cctpConfig?: CCTPConfig;\n}\n\ntype SweepCCTPActionArguments = Record<string, unknown>;\n\nexport function createSweepCCTPActionArguments(\n payload: SweepCCTPEphemeralPayload,\n): SweepCCTPActionArguments {\n const cctpConfig = payload.cctpConfig ?? defaultCCTPConfig;\n const destinationDomain = resolveCCTPDomain(\n payload.destinationChainId,\n cctpConfig,\n );\n\n return {\n [PaymentAction.SweepCCTP]: {\n token: payload.token,\n destinationDomain,\n /* CCTP requires the recipient address to be padded to 32 bytes */\n destinationMintRecipient: pad(payload.destinationMintRecipient, {\n size: 32,\n }),\n threshold: payload.threshold,\n endBalance: payload.endBalance,\n fee: payload.fee,\n },\n };\n}\n\nfunction resolveCCTPDomain(\n destinationChainId: number,\n cctpConfig: CCTPConfig,\n): number {\n const domain = cctpConfig.getDomain(destinationChainId);\n\n if (domain === null) {\n throw new Error(`Chain ${destinationChainId} does not support CCTP`);\n }\n\n return domain;\n}\n", "import type { BaseEphemeralInstructionPayload } from \"../types\";\nimport type { Address } from \"@otim/utils/schemas\";\n\nimport { PaymentAction } from \"../types\";\n\nexport interface SweepERC20EphemeralPayload\n extends BaseEphemeralInstructionPayload {\n token: Address;\n target: Address;\n threshold: string;\n endBalance: string;\n}\n\ntype SweepERC20ActionArguments = Record<string, unknown>;\n\nexport function createSweepERC20ActionArguments(\n payload: SweepERC20EphemeralPayload,\n): SweepERC20ActionArguments {\n return {\n [PaymentAction.SweepERC20]: {\n token: payload.token,\n target: payload.target,\n threshold: payload.threshold,\n endBalance: payload.endBalance,\n fee: payload.fee,\n },\n };\n}\n", "import type {\n BaseEphemeralInstructionPayload,\n UniswapV3FeeTier,\n} from \"../types\";\nimport type { Address } from \"@otim/utils/schemas\";\n\nimport { PaymentAction } from \"../types\";\n\nexport interface SweepUniswapV3EphemeralPayload\n extends BaseEphemeralInstructionPayload {\n recipient: Address;\n tokenIn: Address;\n tokenOut: Address;\n feeTier: UniswapV3FeeTier;\n threshold: string;\n endBalance: string;\n floorAmountOut: string;\n meanPriceLookBack: number;\n maxPriceDeviationBps: number;\n}\n\ntype SweepUniswapV3ActionArguments = Record<string, unknown>;\n\nexport function createSweepUniswapV3ActionArguments(\n payload: SweepUniswapV3EphemeralPayload,\n): SweepUniswapV3ActionArguments {\n return {\n [PaymentAction.SweepUniswapV3]: {\n recipient: payload.recipient,\n tokenIn: payload.tokenIn,\n tokenOut: payload.tokenOut,\n feeTier: payload.feeTier,\n threshold: payload.threshold,\n endBalance: payload.endBalance,\n floorAmountOut: payload.floorAmountOut,\n meanPriceLookBack: payload.meanPriceLookBack,\n maxPriceDeviationBps: payload.maxPriceDeviationBps,\n fee: payload.fee,\n },\n };\n}\n", "import type { BaseEphemeralInstructionPayload } from \"../types\";\nimport type { Address } from \"@otim/utils/schemas\";\n\nimport { toHex } from \"viem\";\n\nimport { PaymentAction } from \"../types\";\n\nexport interface SweepEphemeralPayload extends BaseEphemeralInstructionPayload {\n target: Address;\n threshold: string;\n endBalance: string;\n gasLimit: number;\n}\n\ntype SweepActionArguments = Record<string, unknown>;\n\nexport function createSweepActionArguments(\n payload: SweepEphemeralPayload,\n): SweepActionArguments {\n return {\n [PaymentAction.Sweep]: {\n target: payload.target,\n threshold: payload.threshold,\n endBalance: payload.endBalance,\n gasLimit: toHex(payload.gasLimit),\n fee: payload.fee,\n },\n };\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"deactivateInstruction\", \"type\": \"DeactivateInstruction\" }\n ],\n \"DeactivateInstruction\": [\n { \"name\": \"instructionId\", \"type\": \"bytes32\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"refuelERC20\", \"type\": \"RefuelERC20\" }\n ],\n \"RefuelERC20\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"target\", \"type\": \"address\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"endBalance\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"refuel\", \"type\": \"Refuel\" }\n ],\n \"Refuel\": [\n { \"name\": \"target\", \"type\": \"address\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"endBalance\", \"type\": \"uint256\" },\n { \"name\": \"gasLimit\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"sweepCCTP\", \"type\": \"SweepCCTP\" }\n ],\n \"SweepCCTP\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"destinationDomain\", \"type\": \"uint32\" },\n { \"name\": \"destinationMintRecipient\", \"type\": \"bytes32\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"endBalance\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"sweepDepositAccountERC20\", \"type\": \"SweepDepositAccountERC20\" }\n ],\n \"SweepDepositAccountERC20\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"depositor\", \"type\": \"address\" },\n { \"name\": \"recipient\", \"type\": \"address\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"sweepDepositAccount\", \"type\": \"SweepDepositAccount\" }\n ],\n \"SweepDepositAccount\": [\n { \"name\": \"depositor\", \"type\": \"address\" },\n { \"name\": \"recipient\", \"type\": \"address\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"sweepERC20\", \"type\": \"SweepERC20\" }\n ],\n \"SweepERC20\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"target\", \"type\": \"address\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"endBalance\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n {\n \"name\": \"sweepSkipCCTPDepositAccount\",\n \"type\": \"SweepSkipCCTPDepositAccount\"\n }\n ],\n \"SweepSkipCCTPDepositAccount\": [\n { \"name\": \"depositor\", \"type\": \"address\" },\n { \"name\": \"destinationDomain\", \"type\": \"uint32\" },\n { \"name\": \"destinationMintRecipient\", \"type\": \"bytes32\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"sweepUniswapV3\", \"type\": \"SweepUniswapV3\" }\n ],\n \"SweepUniswapV3\": [\n { \"name\": \"recipient\", \"type\": \"address\" },\n { \"name\": \"tokenIn\", \"type\": \"address\" },\n { \"name\": \"tokenOut\", \"type\": \"address\" },\n { \"name\": \"feeTier\", \"type\": \"uint24\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"endBalance\", \"type\": \"uint256\" },\n { \"name\": \"floorAmountOut\", \"type\": \"uint256\" },\n { \"name\": \"meanPriceLookBack\", \"type\": \"uint32\" },\n { \"name\": \"maxPriceDeviationBPS\", \"type\": \"uint32\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"sweep\", \"type\": \"Sweep\" }\n ],\n \"Sweep\": [\n { \"name\": \"target\", \"type\": \"address\" },\n { \"name\": \"threshold\", \"type\": \"uint256\" },\n { \"name\": \"endBalance\", \"type\": \"uint256\" },\n { \"name\": \"gasLimit\", \"type\": \"uint256\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"transferERC20\", \"type\": \"TransferERC20\" }\n ],\n \"TransferERC20\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"target\", \"type\": \"address\" },\n { \"name\": \"value\", \"type\": \"uint256\" },\n { \"name\": \"schedule\", \"type\": \"Schedule\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Schedule\": [\n { \"name\": \"startAt\", \"type\": \"uint256\" },\n { \"name\": \"startBy\", \"type\": \"uint256\" },\n { \"name\": \"interval\", \"type\": \"uint256\" },\n { \"name\": \"timeout\", \"type\": \"uint256\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"transfer\", \"type\": \"Transfer\" }\n ],\n \"Transfer\": [\n { \"name\": \"target\", \"type\": \"address\" },\n { \"name\": \"value\", \"type\": \"uint256\" },\n { \"name\": \"gasLimit\", \"type\": \"uint256\" },\n { \"name\": \"schedule\", \"type\": \"Schedule\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Schedule\": [\n { \"name\": \"startAt\", \"type\": \"uint256\" },\n { \"name\": \"startBy\", \"type\": \"uint256\" },\n { \"name\": \"interval\", \"type\": \"uint256\" },\n { \"name\": \"timeout\", \"type\": \"uint256\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "{\n \"types\": {\n \"Instruction\": [\n { \"name\": \"salt\", \"type\": \"uint256\" },\n { \"name\": \"maxExecutions\", \"type\": \"uint256\" },\n { \"name\": \"action\", \"type\": \"address\" },\n { \"name\": \"uniswapV3ExactInput\", \"type\": \"UniswapV3ExactInput\" }\n ],\n \"UniswapV3ExactInput\": [\n { \"name\": \"recipient\", \"type\": \"address\" },\n { \"name\": \"tokenIn\", \"type\": \"address\" },\n { \"name\": \"tokenOut\", \"type\": \"address\" },\n { \"name\": \"feeTier\", \"type\": \"uint24\" },\n { \"name\": \"amountIn\", \"type\": \"uint256\" },\n { \"name\": \"floorAmountOut\", \"type\": \"uint256\" },\n { \"name\": \"meanPriceLookBack\", \"type\": \"uint32\" },\n { \"name\": \"maxPriceDeviationBPS\", \"type\": \"uint32\" },\n { \"name\": \"schedule\", \"type\": \"Schedule\" },\n { \"name\": \"fee\", \"type\": \"Fee\" }\n ],\n \"Schedule\": [\n { \"name\": \"startAt\", \"type\": \"uint256\" },\n { \"name\": \"startBy\", \"type\": \"uint256\" },\n { \"name\": \"interval\", \"type\": \"uint256\" },\n { \"name\": \"timeout\", \"type\": \"uint256\" }\n ],\n \"Fee\": [\n { \"name\": \"token\", \"type\": \"address\" },\n { \"name\": \"maxBaseFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"maxPriorityFeePerGas\", \"type\": \"uint256\" },\n { \"name\": \"executionFee\", \"type\": \"uint256\" }\n ]\n }\n}\n", "import type { Address } from \"@otim/utils/schemas\";\n\nimport deactivateInstructionTypes from \"./contracts/schemas/eip-712/actions/deactivate-instruction.json\";\nimport refuelERC20Types from \"./contracts/schemas/eip-712/actions/refuel-erc20.json\";\nimport refuelTypes from \"./contracts/schemas/eip-712/actions/refuel.json\";\nimport sweepCCTPTypes from \"./contracts/schemas/eip-712/actions/sweep-cctp.json\";\nimport sweepDepositAccountERC20Types from \"./contracts/schemas/eip-712/actions/sweep-deposit-account-erc20.json\";\nimport sweepDepositAccountTypes from \"./contracts/schemas/eip-712/actions/sweep-deposit-account.json\";\nimport sweepERC20Types from \"./contracts/schemas/eip-712/actions/sweep-erc20.json\";\nimport sweepSkipCCTPDepositAccountTypes from \"./contracts/schemas/eip-712/actions/sweep-skip-cctp-deposit-account.json\";\nimport sweepUniswapV3Types from \"./contracts/schemas/eip-712/actions/sweep-uniswap-v3.json\";\nimport sweepTypes from \"./contracts/schemas/eip-712/actions/sweep.json\";\nimport transferERC20Types from \"./contracts/schemas/eip-712/actions/transfer-erc20.json\";\nimport transferTypes from \"./contracts/schemas/eip-712/actions/transfer.json\";\nimport uniswapV3ExactInputTypes from \"./contracts/schemas/eip-712/actions/uniswap-v3-exact-input.json\";\n\n/**\n * EIP-712 types structure for instruction signatures.\n */\nexport interface EIP712Types {\n types: {\n [key: string]: Array<{ name: string; type: string }>;\n Instruction: Array<{ name: string; type: string }>;\n };\n}\n\n/**\n * Map of instruction actions to their EIP-712 type definitions.\n * Used for creating typed data structures for instruction signatures.\n *\n * @example\n * ```ts\n * const types = eip712TypesMap['transfer'];\n * ```\n */\nexport const eip712TypesMap = {\n refuel: refuelTypes,\n refuelERC20: refuelERC20Types,\n transfer: transferTypes,\n transferERC20: transferERC20Types,\n uniswapV3ExactInput: uniswapV3ExactInputTypes,\n sweep: sweepTypes,\n sweepERC20: sweepERC20Types,\n sweepCCTP: sweepCCTPTypes,\n sweepUniswapV3: sweepUniswapV3Types,\n sweepDepositAccount: sweepDepositAccountTypes,\n sweepDepositAccountERC20: sweepDepositAccountERC20Types,\n sweepSkipCCTPDepositAccount: sweepSkipCCTPDepositAccountTypes,\n deactivateInstruction: deactivateInstructionTypes,\n} as const satisfies Partial<Record<string, EIP712Types>>;\n\n/**\n * Base instruction build payload containing fields common to all instructions.\n */\nexport interface BaseInstructionBuildPayload {\n // Account address that will execute the instruction\n address: Address;\n // Chain ID where the instruction will be executed\n chainId: number;\n // Maximum number of times the instruction can be executed (0 = unlimited)\n maxExecutions: number;\n // Optional salt for uniqueness\n salt?: number;\n // Fee configuration for instruction execution\n fee: {\n executionFee: string;\n maxBaseFeePerGas: string;\n maxPriorityFeePerGas: string;\n token: Address;\n };\n}\n\n/**\n * Extended base payload for instructions that support scheduling.\n * Includes all base fields plus schedule configuration.\n */\nexport interface ScheduledInstructionBuildPayload\n extends BaseInstructionBuildPayload {\n // Schedule configuration for when and how often the instruction runs\n schedule: {\n // Unix timestamp (seconds) when instruction should start (0 = immediate)\n startAt: number;\n // Unix timestamp (seconds) by which instruction must start (0 = no deadline)\n startBy: number;\n // Interval (seconds) between executions\n interval: number;\n // Maximum latency (seconds) allowed for scheduled execution (0 = no limit)\n timeout: number;\n };\n}\n\n/**\n * Extended payload for instructions that support an optional token parameter.\n * This is typically used for ERC20 variants of actions.\n */\nexport interface TokenInstructionPayload {\n // Optional token address (if not provided, uses native currency)\n token?: Address;\n}\n\n/**\n * Extended payload for instructions that support gas limit configuration.\n * Used by actions like transfer and refuel.\n */\nexport interface GasLimitConfigurablePayload {\n // Optional gas limit for the action (0 or undefined = auto)\n gasLimit?: number;\n}\n", "import type { EIP712Types } from \"@otim/utils/instructions\";\nimport type { AbiParameter } from \"abitype\";\n\nimport { eip712TypesMap } from \"@otim/utils/instructions\";\n\nconst feeAbiComponent = {\n name: \"fee\",\n type: \"tuple\",\n components: [\n { name: \"token\", type: \"address\" },\n { name: \"maxBaseFeePerGas\", type: \"uint256\" },\n { name: \"maxPriorityFeePerGas\", type: \"uint256\" },\n { name: \"executionFee\", type: \"uint256\" },\n ],\n} as const satisfies AbiParameter;\n\nconst sweepAbi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"target\", type: \"address\" },\n { name: \"threshold\", type: \"uint256\" },\n { name: \"endBalance\", type: \"uint256\" },\n { name: \"gasLimit\", type: \"uint256\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst sweepERC20Abi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"token\", type: \"address\" },\n { name: \"target\", type: \"address\" },\n { name: \"threshold\", type: \"uint256\" },\n { name: \"endBalance\", type: \"uint256\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst sweepCCTPAbi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"token\", type: \"address\" },\n { name: \"destinationDomain\", type: \"uint32\" },\n { name: \"destinationMintRecipient\", type: \"bytes32\" },\n { name: \"threshold\", type: \"uint256\" },\n { name: \"endBalance\", type: \"uint256\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst sweepUniswapV3Abi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"recipient\", type: \"address\" },\n { name: \"tokenIn\", type: \"address\" },\n { name: \"tokenOut\", type: \"address\" },\n { name: \"feeTier\", type: \"uint24\" },\n { name: \"threshold\", type: \"uint256\" },\n { name: \"endBalance\", type: \"uint256\" },\n { name: \"floorAmountOut\", type: \"uint256\" },\n { name: \"meanPriceLookBack\", type: \"uint32\" },\n { name: \"maxPriceDeviationBPS\", type: \"uint32\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst sweepDepositAccountAbi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"depositor\", type: \"address\" },\n { name: \"recipient\", type: \"address\" },\n { name: \"threshold\", type: \"uint256\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst sweepDepositAccountERC20Abi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"token\", type: \"address\" },\n { name: \"depositor\", type: \"address\" },\n { name: \"recipient\", type: \"address\" },\n { name: \"threshold\", type: \"uint256\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst sweepSkipCCTPDepositAccountAbi: readonly AbiParameter[] = [\n {\n type: \"tuple\",\n components: [\n { name: \"depositor\", type: \"address\" },\n { name: \"destinationDomain\", type: \"uint32\" },\n { name: \"destinationMintRecipient\", type: \"bytes32\" },\n { name: \"threshold\", type: \"uint256\" },\n feeAbiComponent,\n ],\n },\n] as const;\n\nconst actionAbiMap = {\n sweep: sweepAbi,\n sweepERC20: sweepERC20Abi,\n sweepCCTP: sweepCCTPAbi,\n sweepUniswapV3: sweepUniswapV3Abi,\n sweepDepositAccount: sweepDepositAccountAbi,\n sweepDepositAccountERC20: sweepDepositAccountERC20Abi,\n sweepSkipCCTPDepositAccount: sweepSkipCCTPDepositAccountAbi,\n} as const;\n\nexport interface InstructionTypeDefinition {\n abi: readonly AbiParameter[];\n eip712Types: EIP712Types;\n}\n\ntype ActionName = keyof typeof actionAbiMap;\n\nclass InstructionTypeRegistry {\n private registry = new Map<string, InstructionTypeDefinition>();\n\n constructor() {\n this.initializeDefaultTypes();\n }\n\n register(actionName: string, definition: InstructionTypeDefinition): void {\n this.registry.set(actionName, definition);\n }\n\n get(actionName: string): InstructionTypeDefinition {\n const definition = this.registry.get(actionName);\n\n if (!definition) {\n throw this.createUnsupportedTypeError(actionName);\n }\n\n return definition;\n }\n\n has(actionName: string): boolean {\n return this.registry.has(actionName);\n }\n\n getAvailableTypes(): string[] {\n return Array.from(this.registry.keys());\n }\n\n private initializeDefaultTypes(): void {\n const actionNames = Object.keys(actionAbiMap) as ActionName[];\n\n for (const actionName of actionNames) {\n const abi = actionAbiMap[actionName];\n const eip712Types = eip712TypesMap[actionName];\n\n if (abi && eip712Types) {\n this.register(actionName, { abi, eip712Types });\n }\n }\n }\n\n private createUnsupportedTypeError(actionName: string): Error {\n const availableTypes = this.getAvailableTypes().join(\", \");\n return new Error(\n `Unsupported instruction type: ${actionName}. Available: ${availableTypes}`,\n );\n }\n}\n\nexport const instructionRegistry = new InstructionTypeRegistry();\n", "import type { PaymentRequestBuildResponse } from \"@otim/utils/api\";\nimport type { Optional } from \"@otim/utils/helpers\";\n\ninterface InstructionWithActionName {\n actionName?: string;\n}\n\nexport interface PaymentResponseWithActionNames\n extends PaymentRequestBuildResponse {\n completionInstructions: Array<\n PaymentRequestBuildResponse[\"completionInstructions\"][number] &\n InstructionWithActionName\n >;\n instructions: Array<\n PaymentRequestBuildResponse[\"instructions\"][number] &\n InstructionWithActionName\n >;\n}\n\ninterface InstructionWithArguments {\n actionArguments: Record<string, unknown>;\n}\n\ntype ActionNamesMap = Record<number, string>;\n\nexport function addActionNamesToInstructions(\n buildResponse: PaymentRequestBuildResponse,\n actionNames: ActionNamesMap,\n): PaymentResponseWithActionNames {\n const completionInstructionCount =\n buildResponse.completionInstructions.length;\n\n return {\n ...buildResponse,\n completionInstructions: buildResponse.completionInstructions.map(\n (instruction, index) => ({\n ...instruction,\n actionName: actionNames[index],\n }),\n ),\n instructions: buildResponse.instructions.map((instruction, index) => ({\n ...instruction,\n actionName: actionNames[completionInstructionCount + index],\n })),\n };\n}\n\nexport function extractActionNamesMap(\n completionInstructions: InstructionWithArguments[],\n instructions: InstructionWithArguments[] = [],\n): ActionNamesMap {\n const allInstructions = [...completionInstructions, ...instructions];\n\n return allInstructions.reduce<ActionNamesMap>(\n (actionNamesMap, instruction, index) => {\n const actionName = getFirstActionArgumentKey(instruction.actionArguments);\n if (actionName) {\n actionNamesMap[index] = actionName;\n }\n return actionNamesMap;\n },\n {},\n );\n}\n\nfunction getFirstActionArgumentKey(\n actionArguments: Record<string, unknown>,\n): Optional<string> {\n const keys = Object.keys(actionArguments);\n return keys[0];\n}\n", "interface SignatureCountAssertion {\n expected: number;\n received: number;\n}\n\n/**\n * Used to validate the number of signatures in a payment request.\n */\nexport class SignatureValidator {\n static assertExactCount(context: SignatureCountAssertion): void {\n if (context.received !== context.expected) {\n throw new Error(\n `Signature count mismatch: expected ${context.expected}, received ${context.received}`,\n );\n }\n }\n\n static assertMinimumCount(context: SignatureCountAssertion): void {\n if (context.received < context.expected) {\n throw new Error(\n `Insufficient signatures: expected at least ${context.expected}, received ${context.received}`,\n );\n }\n }\n}\n\nexport function assertSignatureCount<T>(\n signatures: T[],\n expectedCount: number,\n): asserts signatures is T[] & { length: typeof expectedCount } {\n SignatureValidator.assertExactCount({\n expected: expectedCount,\n received: signatures.length,\n });\n}\n\nexport function assertMinimumSignatures<T>(\n signatures: T[],\n minimumCount: number,\n): asserts signatures is T[] & { length: number } {\n SignatureValidator.assertMinimumCount({\n expected: minimumCount,\n received: signatures.length,\n });\n}\n", "import type { HexString } from \"../schemas\";\nimport type { ChainTokenConfig } from \"./comprehensive-payment-request\";\n\ninterface Token {\n address: string;\n symbol: string;\n chainId: number;\n decimals: number;\n}\n\nexport function createChainTokenConfigs(tokens: Token[]): ChainTokenConfig[] {\n const tokensByChain = groupTokensByChainId(tokens);\n return convertToChainConfigs(tokensByChain);\n}\n\nfunction groupTokensByChainId(tokens: Token[]): Map<number, Token[]> {\n const grouped = new Map<number, Token[]>();\n\n for (const token of tokens) {\n const chainTokens = grouped.get(token.chainId) ?? [];\n chainTokens.push(token);\n grouped.set(token.chainId, chainTokens);\n }\n\n return grouped;\n}\n\nfunction convertToChainConfigs(\n tokensByChain: Map<number, Token[]>,\n): ChainTokenConfig[] {\n return Array.from(tokensByChain.entries()).map(([chainId, tokens]) => ({\n chainId,\n tokens: tokens.map((token) => ({\n symbol: token.symbol,\n address: token.address as HexString,\n decimals: token.decimals,\n })),\n }));\n}\n", "import type { Nullable, Nullish } from \"@otim/utils/helpers\";\nimport type { Address } from \"@otim/utils/schemas\";\n\nimport { isStablecoin } from \"@otim/utils/chains\";\nimport { DEFAULT_ADDRESS } from \"@otim/utils/helpers\";\n\ninterface Token {\n symbol: string;\n address: string;\n}\n\n/**\n * Checks if a token is the native blockchain token (ETH)\n */\nexport function isNativeToken<T extends Pick<Token, \"symbol\" | \"address\">>(\n token: Nullish<T>,\n): boolean {\n if (!token) {\n return false;\n }\n\n return (\n token.symbol === \"ETH\" ||\n token.address.toLowerCase() === DEFAULT_ADDRESS.toLowerCase()\n );\n}\n\ninterface ResolveStablecoinParams<T extends Token> {\n preferredToken: Nullish<T>;\n getStablecoinBySymbol: (symbol: string) => Nullable<T>;\n}\n\n/**\n * Resolves the stablecoin to use for a payment request.\n * Falls back to USDC or USDT if the preferred token is invalid.\n */\nexport function resolvePreferredStablecoin<T extends Token>({\n preferredToken,\n getStablecoinBySymbol,\n}: ResolveStablecoinParams<T>): Nullable<T> {\n const stablecoin = getValidStablecoin(preferredToken);\n if (stablecoin) {\n return stablecoin;\n }\n\n return getDefaultStablecoin(getStablecoinBySymbol);\n}\n\n/**\n * Validates that a token is a non-native stablecoin\n */\nfunction getValidStablecoin<T extends Token>(token: Nullish<T>): Nullable<T> {\n if (!token || isNativeToken(token) || !isStablecoin(token.symbol)) {\n return null;\n }\n\n return token;\n}\n\n/**\n * Returns a default stablecoin with priority: USDC > USDT\n */\nfunction getDefaultStablecoin<T extends Token>(\n getStablecoinBySymbol: (symbol: string) => Nullable<T>,\n): Nullable<T> {\n const usdc = getStablecoinBySymbol(\"USDC\");\n if (usdc) {\n return usdc;\n }\n\n const usdt = getStablecoinBySymbol(\"USDT\");\n if (usdt) {\n return usdt;\n }\n\n return null;\n}\n\n/**\n * Creates a unique identifier for a token by combining chain ID and address\n */\nexport function createTokenIdentifier(\n chainId: number,\n tokenAddress: Address,\n): string {\n return `${chainId}:${tokenAddress}`;\n}\n", "/**\n * Payment Metadata Builder\n *\n * Handles metadata construction for payment requests with two distinct flows:\n * manual payments (user-entered data) and invoice-based payments (from\n * integrations). Ensures consistent metadata structure across both flows while\n * preventing data conflicts.\n */\n\nimport type { InvoiceMetadata } from \"./payment-metadata\";\nimport type { Nullable } from \"@otim/utils/helpers\";\nimport type { PaymentRequestMetadata } from \"@otim/utils/payments\";\n\nimport { isNumber, isValidDate } from \"@otim/utils/helpers\";\n\n/**\n * Default currency for payments\n */\nconst DEFAULT_CURRENCY = \"USD\" as const;\n\n/**\n * Configuration for manual payment request metadata\n */\nexport interface BuildPaymentMetadataParams {\n tokenSymbol: string;\n note?: string;\n dueDate?: string;\n amountInUSD?: Nullable<number>;\n /**\n * Prevents amount/currency conflicts when invoice metadata will be merged\n * later.\n */\n hasInvoiceMetadata?: boolean;\n fromAccountAddress?: string;\n}\n\n/**\n * Configuration for merging invoice data with payment metadata\n */\nexport interface BuildInvoiceMetadataParams {\n invoiceMetadata: InvoiceMetadata;\n baseMetadata: PaymentRequestMetadata;\n}\n\n/**\n * Validates that a value is a safe, finite number suitable for monetary\n * amounts. Excludes NaN and Infinity which could cause calculation errors\n * downstream.\n */\nfunction isValidAmount(value: unknown): value is number {\n return isNumber(value) && Number.isFinite(value);\n}\n\n/**\n * Constructs payment metadata for manually created payment requests.\n * Conditionally includes amount/currency to avoid conflicts when invoice data\n * will be merged later (invoice data should be the source of truth for amounts).\n */\nexport function buildPaymentMetadata(\n params: BuildPaymentMetadataParams,\n): PaymentRequestMetadata {\n const {\n note,\n tokenSymbol,\n dueDate,\n amountInUSD,\n hasInvoiceMetadata = false,\n fromAccountAddress,\n } = params;\n\n const metadata: PaymentRequestMetadata = {\n token: tokenSymbol,\n };\n\n /**\n * Exclude amount/currency when invoice metadata exists to prevent\n * discrepancies between manually entered and invoice-sourced amounts\n */\n if (!hasInvoiceMetadata) {\n if (isValidAmount(amountInUSD)) {\n metadata.amountDue = amountInUSD.toFixed(2);\n }\n metadata.currency = DEFAULT_CURRENCY;\n }\n\n if (dueDate) {\n metadata.dueDate = dueDate;\n }\n\n if (note) {\n metadata.note = note;\n }\n\n if (fromAccountAddress) {\n metadata.fromAccountAddress = fromAccountAddress;\n }\n\n return metadata;\n}\n\n/**\n * Merges invoice data from external integrations (Stripe, QuickBooks,\n * Bill.com, Clio) with base payment metadata. Invoice fields override manual\n * entries to ensure accuracy and maintain audit trail through source/invoiceId\n * tracking.\n */\nexport function buildInvoiceMetadata(\n params: BuildInvoiceMetadataParams,\n): PaymentRequestMetadata {\n const { invoiceMetadata, baseMetadata } = params;\n\n return {\n ...baseMetadata,\n /**\n * Invoice amounts/dates are authoritative - they override any manually\n * entered values to prevent sync issues with external systems\n */\n amountDue: Number(invoiceMetadata.amount).toFixed(2),\n currency: invoiceMetadata.currency,\n dueDate: invoiceMetadata.dueDate,\n /** Preserve user's manual note if invoice doesn't provide one */\n note: invoiceMetadata.description ?? baseMetadata.note,\n /** Track integration source for reconciliation and debugging */\n source: invoiceMetadata.source,\n invoiceId: invoiceMetadata.invoiceId,\n invoiceNumber: invoiceMetadata.invoiceNumber,\n };\n}\n\n/**\n * Validates metadata structure before sending to backend API.\n * Catches type mismatches and invalid values that would cause payment\n * creation failures or blockchain transaction errors.\n */\nexport function validatePaymentMetadata(metadata: PaymentRequestMetadata): {\n isValid: boolean;\n errors: string[];\n} {\n const errors: string[] = [];\n\n /** Token symbol is required for all payment types (stablecoin or native) */\n const token = metadata[\"token\"];\n if (!token || typeof token !== \"string\") {\n errors.push(\"Token symbol is required\");\n }\n\n /**\n * Amount validation handles both string and number types since\n * different integrations may provide amounts in different formats\n */\n const amountDue = metadata[\"amountDue\"];\n if (amountDue !== undefined && amountDue !== null) {\n const amount =\n typeof amountDue === \"string\" ? parseFloat(amountDue) : Number(amountDue);\n if (!isValidAmount(amount) || amount < 0) {\n errors.push(\"Amount must be a valid positive number\");\n }\n }\n\n /**\n * Due dates must be valid ISO strings for consistent timezone handling\n * and proper comparison in payment status calculations\n */\n const dueDate = metadata[\"dueDate\"];\n if (dueDate !== undefined && dueDate !== null) {\n if (typeof dueDate !== \"string\") {\n errors.push(\"Due date must be a string\");\n } else {\n const date = new Date(dueDate);\n if (!isValidDate(date)) {\n errors.push(\"Due date must be a valid ISO date string\");\n }\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["toHex", "toHex"]
7
7
  }
@@ -76,7 +76,7 @@ var import_axios = __toESM(require("axios"));
76
76
 
77
77
  // src/env.ts
78
78
  var BUILD_MODE = "development";
79
- var APP_API_URL = "https://app.otim.com/api";
79
+ var APP_API_URL = "http://localhost:3000/api";
80
80
 
81
81
  // src/helpers/logger.ts
82
82
  var Logger = class {
@@ -405,14 +405,14 @@ var upsertIntegration = async (request) => {
405
405
  // src/server/routes/payments.ts
406
406
  var buildPaymentRequest = async (request) => {
407
407
  const response = await appApiClient.post(
408
- "/payment/request/build",
408
+ "/orchestration/build",
409
409
  request
410
410
  );
411
411
  return response.data;
412
412
  };
413
413
  var newPaymentRequest = async (request) => {
414
414
  const response = await appApiClient.post(
415
- "/payment/request/new",
415
+ "/orchestration/new",
416
416
  request
417
417
  );
418
418
  return response.data;