@pafi-dev/core 0.3.0-beta.0 → 0.3.0-beta.10

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 (87) hide show
  1. package/dist/abi/index.cjs +2 -6
  2. package/dist/abi/index.cjs.map +1 -1
  3. package/dist/abi/index.d.cts +1 -286
  4. package/dist/abi/index.d.ts +1 -286
  5. package/dist/abi/index.js +1 -5
  6. package/dist/{chunk-R4L66ZR5.js → chunk-73CQTNLB.js} +10 -1
  7. package/dist/chunk-73CQTNLB.js.map +1 -0
  8. package/dist/{chunk-5YH4D7QF.js → chunk-7UBO7DY5.js} +1 -1
  9. package/dist/{chunk-FGKLDKJK.cjs → chunk-ALCWYDVG.cjs} +1 -1
  10. package/dist/{chunk-FGKLDKJK.cjs.map → chunk-ALCWYDVG.cjs.map} +1 -1
  11. package/dist/{chunk-X3I5XWAR.cjs → chunk-CQCSQPWG.cjs} +2 -15
  12. package/dist/chunk-CQCSQPWG.cjs.map +1 -0
  13. package/dist/{chunk-CWP4PFOP.cjs → chunk-DMW67WBU.cjs} +11 -2
  14. package/dist/chunk-DMW67WBU.cjs.map +1 -0
  15. package/dist/{chunk-C4ZDYG4D.js → chunk-DUY7Z2AI.js} +48 -6
  16. package/dist/chunk-DUY7Z2AI.js.map +1 -0
  17. package/dist/chunk-EDR5SFJN.cjs +351 -0
  18. package/dist/chunk-EDR5SFJN.cjs.map +1 -0
  19. package/dist/{chunk-FIKTQR7H.js → chunk-I2P3TIP7.js} +2 -2
  20. package/dist/{chunk-BNTVOKYT.cjs → chunk-KJKDLD7N.cjs} +51 -9
  21. package/dist/chunk-KJKDLD7N.cjs.map +1 -0
  22. package/dist/{chunk-VQSRCMMK.js → chunk-QGO6X6LG.js} +2 -15
  23. package/dist/chunk-QGO6X6LG.js.map +1 -0
  24. package/dist/chunk-W23EJNYG.js +351 -0
  25. package/dist/chunk-W23EJNYG.js.map +1 -0
  26. package/dist/{chunk-CAE2BVKI.cjs → chunk-Z2V525IS.cjs} +6 -6
  27. package/dist/{chunk-CAE2BVKI.cjs.map → chunk-Z2V525IS.cjs.map} +1 -1
  28. package/dist/contract/index.cjs +2 -5
  29. package/dist/contract/index.cjs.map +1 -1
  30. package/dist/contract/index.d.cts +2 -4
  31. package/dist/contract/index.d.ts +2 -4
  32. package/dist/contract/index.js +1 -4
  33. package/dist/eip712/index.cjs +9 -3
  34. package/dist/eip712/index.cjs.map +1 -1
  35. package/dist/eip712/index.d.cts +44 -2
  36. package/dist/eip712/index.d.ts +44 -2
  37. package/dist/eip712/index.js +8 -2
  38. package/dist/index-B06IJlHe.d.ts +244 -0
  39. package/dist/index-B7pGBych.d.cts +244 -0
  40. package/dist/index.cjs +365 -329
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.cts +778 -459
  43. package/dist/index.d.ts +778 -459
  44. package/dist/index.js +383 -347
  45. package/dist/index.js.map +1 -1
  46. package/dist/quoting/index.cjs +3 -3
  47. package/dist/quoting/index.d.cts +1 -1
  48. package/dist/quoting/index.d.ts +1 -1
  49. package/dist/quoting/index.js +2 -2
  50. package/dist/swap/index.cjs +4 -3
  51. package/dist/swap/index.cjs.map +1 -1
  52. package/dist/swap/index.d.cts +3 -84
  53. package/dist/swap/index.d.ts +3 -84
  54. package/dist/swap/index.js +3 -2
  55. package/dist/{types-BDOnH5Le.d.ts → types-b5_Tokjl.d.cts} +8 -17
  56. package/dist/{types-BDOnH5Le.d.cts → types-b5_Tokjl.d.ts} +8 -17
  57. package/package.json +1 -1
  58. package/dist/chunk-27V32VNM.cjs +0 -370
  59. package/dist/chunk-27V32VNM.cjs.map +0 -1
  60. package/dist/chunk-4RYBJLF3.js +0 -370
  61. package/dist/chunk-4RYBJLF3.js.map +0 -1
  62. package/dist/chunk-5QJZT7VB.cjs +0 -46
  63. package/dist/chunk-5QJZT7VB.cjs.map +0 -1
  64. package/dist/chunk-6I6K43RQ.cjs +0 -149
  65. package/dist/chunk-6I6K43RQ.cjs.map +0 -1
  66. package/dist/chunk-BNTVOKYT.cjs.map +0 -1
  67. package/dist/chunk-C4ZDYG4D.js.map +0 -1
  68. package/dist/chunk-CWP4PFOP.cjs.map +0 -1
  69. package/dist/chunk-L74CZAVQ.cjs +0 -99
  70. package/dist/chunk-L74CZAVQ.cjs.map +0 -1
  71. package/dist/chunk-P56TUGTS.js +0 -46
  72. package/dist/chunk-P56TUGTS.js.map +0 -1
  73. package/dist/chunk-R4L66ZR5.js.map +0 -1
  74. package/dist/chunk-UU72CX7E.js +0 -149
  75. package/dist/chunk-UU72CX7E.js.map +0 -1
  76. package/dist/chunk-VQSRCMMK.js.map +0 -1
  77. package/dist/chunk-X3I5XWAR.cjs.map +0 -1
  78. package/dist/chunk-X4IXUTTD.js +0 -99
  79. package/dist/chunk-X4IXUTTD.js.map +0 -1
  80. package/dist/relay/index.cjs +0 -19
  81. package/dist/relay/index.cjs.map +0 -1
  82. package/dist/relay/index.d.cts +0 -75
  83. package/dist/relay/index.d.ts +0 -75
  84. package/dist/relay/index.js +0 -19
  85. package/dist/relay/index.js.map +0 -1
  86. /package/dist/{chunk-5YH4D7QF.js.map → chunk-7UBO7DY5.js.map} +0 -0
  87. /package/dist/{chunk-FIKTQR7H.js.map → chunk-I2P3TIP7.js.map} +0 -0
package/dist/index.d.cts CHANGED
@@ -1,14 +1,12 @@
1
1
  import { Address, Hex, PublicClient, WalletClient } from 'viem';
2
- import { P as PoolKey, C as ChainConfig, a as PointTokenDomainConfig, E as EIP712Signature, S as SignatureVerification, b as PafiSDKConfig, M as MintRequest, R as ReceiverConsent, c as MintParams, d as SwapParams, B as BestQuote, Q as QuoteResult, e as PathKey } from './types-BDOnH5Le.cjs';
3
- export { I as Issuer } from './types-BDOnH5Le.cjs';
4
- export { erc20Abi, issuerRegistryAbi, mintingOracleAbi, permit2Abi, pointTokenAbi, pointTokenFactoryAbi, relayAbi, universalRouterAbi, v4QuoterAbi } from './abi/index.cjs';
5
- export { buildDomain, buildMintRequestTypedData, buildReceiverConsentTypedData, signMintRequest, signReceiverConsent, verifyMintRequest, verifyReceiverConsent } from './eip712/index.cjs';
6
- import { SimulationResult } from './relay/index.cjs';
7
- export { buildRelaySwapParams, decodeExtData, decodeMintAndSwap, encodeExtData, encodeMintAndSwap, simulateMintAndSwap } from './relay/index.cjs';
8
- export { getIssuer, getMintRequestNonce, getPointTokenBalance, getPointTokenIssuer, getPointTokenIssuerAddress, getReceiverConsentNonce, getTokenName, getUsdt, isActiveIssuer, isMinter, verifyMintCap } from './contract/index.cjs';
2
+ import { P as PoolKey, C as ChainConfig, a as PafiSDKConfig, b as PointTokenDomainConfig, M as MintRequest, R as ReceiverConsent, E as EIP712Signature, S as SignatureVerification, B as BestQuote, Q as QuoteResult } from './types-b5_Tokjl.cjs';
3
+ export { c as BurnRequest, I as Issuer, d as PathKey } from './types-b5_Tokjl.cjs';
4
+ export { erc20Abi, issuerRegistryAbi, mintingOracleAbi, permit2Abi, pointTokenAbi, pointTokenFactoryAbi, universalRouterAbi, v4QuoterAbi } from './abi/index.cjs';
5
+ export { buildBurnRequestTypedData, buildDomain, buildMintRequestTypedData, buildReceiverConsentTypedData, signBurnRequest, signMintRequest, signReceiverConsent, verifyBurnRequest, verifyMintRequest, verifyReceiverConsent } from './eip712/index.cjs';
6
+ export { getIssuer, getMintRequestNonce, getPointTokenBalance, getPointTokenIssuer, getPointTokenIssuerAddress, getReceiverConsentNonce, getTokenName, isActiveIssuer, isMinter, verifyMintCap } from './contract/index.cjs';
9
7
  export { buildAllPaths, combineRoutes, findBestQuote, quoteBestRoute, quoteExactInput, quoteExactInputSingle } from './quoting/index.cjs';
10
- import { SwapSimulationResult } from './swap/index.cjs';
11
- export { SETTLE_ALL, SWAP_EXACT_IN, TAKE_ALL, V4_SWAP, buildErc20ApprovalCalldata, buildPermit2ApprovalCalldata, buildSwapFromQuote, buildUniversalRouterExecuteArgs, buildV4SwapInput, checkAllowance, simulateSwap } from './swap/index.cjs';
8
+ import { P as PartialUserOperation, O as Operation, U as UserOperation, S as SwapSimulationResult } from './index-B7pGBych.cjs';
9
+ export { B as BuildSwapWithGasDeductionParams, E as ENTRY_POINT_V07, a as PaymasterFields, b as SETTLE_ALL, c as SWAP_EXACT_IN, T as TAKE_ALL, d as UserOpReceipt, V as V4_SWAP, Z as ZERO_VALUE, e as buildErc20ApprovalCalldata, f as buildPermit2ApprovalCalldata, g as buildSwapFromQuote, h as buildSwapWithGasDeduction, i as buildUniversalRouterExecuteArgs, j as buildV4SwapInput, k as checkAllowance, s as simulateSwap } from './index-B7pGBych.cjs';
12
10
  import { LoginMessageParams } from './auth/index.cjs';
13
11
  export { VerifyLoginResult, createLoginMessage, parseLoginMessage, verifyLoginMessage } from './auth/index.cjs';
14
12
 
@@ -27,6 +25,21 @@ declare const mintRequestTypes: {
27
25
  readonly type: "uint256";
28
26
  }];
29
27
  };
28
+ declare const burnRequestTypes: {
29
+ readonly BurnRequest: readonly [{
30
+ readonly name: "from";
31
+ readonly type: "address";
32
+ }, {
33
+ readonly name: "amount";
34
+ readonly type: "uint256";
35
+ }, {
36
+ readonly name: "nonce";
37
+ readonly type: "uint256";
38
+ }, {
39
+ readonly name: "deadline";
40
+ readonly type: "uint256";
41
+ }];
42
+ };
30
43
  declare const receiverConsentTypes: {
31
44
  readonly ReceiverConsent: readonly [{
32
45
  readonly name: "onBehalfOf";
@@ -75,72 +88,254 @@ declare class ApiError extends PafiSDKError {
75
88
  }
76
89
 
77
90
  /**
78
- * ERC-4337 v0.7 EntryPoint standard address (deployed deterministically
79
- * at the same address across chains).
80
- * https://eips.ethereum.org/EIPS/eip-4337
91
+ * Orderly Network Vault entrypoint for **perp deposit** flow on
92
+ * Base mainnet (Scenario 3).
93
+ *
94
+ * Source of truth for addresses + integration:
95
+ * https://orderly.network/docs/build-on-omnichain/addresses#base
96
+ *
97
+ * ## Architecture
98
+ *
99
+ * User wallet (Base)
100
+ * │ 1. USDC.approve(vault, amount)
101
+ * │ 2. vault.deposit{value: layerZeroFee}({
102
+ * │ accountId, brokerHash, tokenHash, tokenAmount
103
+ * │ })
104
+ * ▼
105
+ * OrderlyVault (Base)
106
+ * │ — locks USDC, emits LayerZero message
107
+ * ▼
108
+ * Orderly chain (off-chain matching engine)
109
+ * │ — credits the user's perp account
110
+ * ▼
111
+ * User can now place perp orders via Orderly REST/WS API
112
+ *
113
+ * **Important:** `value` is required and is the LayerZero cross-chain
114
+ * fee (paid in native ETH on Base). Quote it via
115
+ * `vault.getDepositFee(user, data)` BEFORE calling deposit. Fees vary
116
+ * with destination chain congestion.
117
+ *
118
+ * ## Sponsored vs direct
119
+ *
120
+ * Coinbase Paymaster sponsors GAS, not `msg.value`. So even on the
121
+ * sponsored path the user MUST hold enough native ETH on Base to cover
122
+ * `getDepositFee()` (typically ~0.0002 ETH at quiet times).
81
123
  */
82
- declare const ENTRY_POINT_V07: Address;
124
+ /** Orderly Vault on Base mainnet (EIP-55 checksum). */
125
+ declare const ORDERLY_VAULT_BASE_MAINNET: Address;
83
126
  /**
84
- * A single call inside a batch. `BatchExecutor.execute(Call[])` iterates
85
- * and invokes each one. When the batch runs via EIP-7702 delegation,
86
- * `msg.sender` for each call is the user's EOA.
127
+ * Per-chain registry of the Orderly Vault. Add chains here as Orderly
128
+ * deploys them.
87
129
  */
88
- interface Operation {
89
- target: Address;
90
- value: bigint;
91
- data: Hex;
92
- }
130
+ declare const ORDERLY_VAULT_ADDRESSES: Record<number, Address>;
93
131
  /**
94
- * Paymaster fields attached to a UserOperation. Populated by the
95
- * Coinbase Paymaster (via PAFI Backend proxy) before the user signs.
132
+ * Pre-computed broker hashes `keccak256(abi.encodePacked(brokerId))`.
133
+ * Add new brokers as they launch.
134
+ *
135
+ * Reference: https://orderly.network/docs/build-on-omnichain/user-flows/accountId
96
136
  */
97
- interface PaymasterFields {
98
- paymaster: Address;
99
- paymasterData: Hex;
100
- paymasterVerificationGasLimit: bigint;
101
- paymasterPostOpGasLimit: bigint;
102
- }
137
+ declare const BROKER_HASHES: {
138
+ /** Default partner broker on Base — most commonly whitelisted. */
139
+ readonly woofi_pro: `0x${string}`;
140
+ /** Orderly's own white-label broker. */
141
+ readonly orderly: `0x${string}`;
142
+ /** LogX. */
143
+ readonly logx: `0x${string}`;
144
+ };
103
145
  /**
104
- * Partial UserOp used during preparation before paymaster fields are
105
- * attached or the user signs.
146
+ * Pre-computed token hashes`keccak256(abi.encodePacked(tokenSymbol))`.
147
+ * The hash maps to the actual ERC-20 address on each chain via
148
+ * `vault.getAllowedToken(tokenHash)`.
149
+ *
150
+ * Note: Orderly canonicalises by symbol (USDC, not "USD Coin").
106
151
  */
107
- interface PartialUserOperation {
108
- sender: Address;
109
- nonce: bigint;
110
- callData: Hex;
111
- callGasLimit: bigint;
112
- verificationGasLimit: bigint;
113
- preVerificationGas: bigint;
114
- maxFeePerGas: bigint;
115
- maxPriorityFeePerGas: bigint;
116
- }
152
+ declare const TOKEN_HASHES: {
153
+ readonly USDC: `0x${string}`;
154
+ };
155
+ /**
156
+ * Compute Orderly's `accountId` — uniquely identifies a user+broker
157
+ * tuple. Matches the off-chain formula used by the Orderly SDK so
158
+ * deposits + future REST API calls reference the same account.
159
+ *
160
+ * accountId = keccak256(abi.encode(user, brokerHash))
161
+ *
162
+ * Note `abi.encode` (not `encodePacked`) — uses 32-byte left-padding.
163
+ */
164
+ declare function computeAccountId(user: Address, brokerHash: Hex): Hex;
117
165
  /**
118
- * Full ERC-4337 v0.7 UserOperation, ready for bundler submission.
166
+ * Minimal Orderly Vault ABI just the functions PAFI needs for
167
+ * Scenario 3 (perp deposit). Full ABI is on Orderly's docs site.
119
168
  */
120
- interface UserOperation extends PartialUserOperation {
121
- paymaster: Address;
122
- paymasterData: Hex;
123
- paymasterVerificationGasLimit: bigint;
124
- paymasterPostOpGasLimit: bigint;
125
- signature: Hex;
169
+ declare const ORDERLY_VAULT_ABI: readonly [{
170
+ readonly type: "function";
171
+ readonly name: "deposit";
172
+ readonly stateMutability: "payable";
173
+ readonly inputs: readonly [{
174
+ readonly name: "data";
175
+ readonly type: "tuple";
176
+ readonly components: readonly [{
177
+ readonly name: "accountId";
178
+ readonly type: "bytes32";
179
+ }, {
180
+ readonly name: "brokerHash";
181
+ readonly type: "bytes32";
182
+ }, {
183
+ readonly name: "tokenHash";
184
+ readonly type: "bytes32";
185
+ }, {
186
+ readonly name: "tokenAmount";
187
+ readonly type: "uint128";
188
+ }];
189
+ }];
190
+ readonly outputs: readonly [];
191
+ }, {
192
+ readonly type: "function";
193
+ readonly name: "getDepositFee";
194
+ readonly stateMutability: "view";
195
+ readonly inputs: readonly [{
196
+ readonly name: "user";
197
+ readonly type: "address";
198
+ }, {
199
+ readonly name: "data";
200
+ readonly type: "tuple";
201
+ readonly components: readonly [{
202
+ readonly name: "accountId";
203
+ readonly type: "bytes32";
204
+ }, {
205
+ readonly name: "brokerHash";
206
+ readonly type: "bytes32";
207
+ }, {
208
+ readonly name: "tokenHash";
209
+ readonly type: "bytes32";
210
+ }, {
211
+ readonly name: "tokenAmount";
212
+ readonly type: "uint128";
213
+ }];
214
+ }];
215
+ readonly outputs: readonly [{
216
+ readonly name: "";
217
+ readonly type: "uint256";
218
+ }];
219
+ }, {
220
+ readonly type: "function";
221
+ readonly name: "getAllowedBroker";
222
+ readonly stateMutability: "view";
223
+ readonly inputs: readonly [{
224
+ readonly name: "brokerHash";
225
+ readonly type: "bytes32";
226
+ }];
227
+ readonly outputs: readonly [{
228
+ readonly name: "";
229
+ readonly type: "bool";
230
+ }];
231
+ }, {
232
+ readonly type: "function";
233
+ readonly name: "getAllowedToken";
234
+ readonly stateMutability: "view";
235
+ readonly inputs: readonly [{
236
+ readonly name: "tokenHash";
237
+ readonly type: "bytes32";
238
+ }];
239
+ readonly outputs: readonly [{
240
+ readonly name: "";
241
+ readonly type: "address";
242
+ }];
243
+ }];
244
+ /** Struct mirror of `IOrderlyVault.VaultDepositFE` for type-safe builders. */
245
+ interface VaultDepositFE {
246
+ accountId: Hex;
247
+ brokerHash: Hex;
248
+ tokenHash: Hex;
249
+ /** uint128 — USDC has 6 decimals. */
250
+ tokenAmount: bigint;
126
251
  }
252
+
127
253
  /**
128
- * Receipt returned by a bundler after a UserOp lands on-chain.
254
+ * v1.5 Scenario 3: deposit USDC from the user's wallet into the
255
+ * Orderly perp Vault on Base mainnet.
256
+ *
257
+ * Builds a `PartialUserOperation` packaging the 2 inner calls:
258
+ *
259
+ * 1. `USDC.approve(orderlyVault, amount)` — let the Vault pull USDC
260
+ * 2. `OrderlyVault.deposit{value: layerZeroFee}(VaultDepositFE)` —
261
+ * transfer USDC into the Vault + emit a LayerZero message that
262
+ * credits the user's perp account on the Orderly chain
263
+ *
264
+ * ## ⚠️ Native ETH constraint
265
+ *
266
+ * Coinbase Paymaster sponsors GAS, **not `msg.value`**. The LayerZero
267
+ * cross-chain fee MUST come from the user's own native ETH balance on
268
+ * Base — even when the rest of the UserOp is sponsored.
269
+ *
270
+ * Quote the fee BEFORE calling this builder via:
271
+ *
272
+ * const fee = await client.readContract({
273
+ * address: orderlyVault,
274
+ * abi: ORDERLY_VAULT_ABI,
275
+ * functionName: 'getDepositFee',
276
+ * args: [user, depositData],
277
+ * });
278
+ *
279
+ * If `user.eth < fee`, surface this error to the FE so the user can
280
+ * top up before retrying — the Vault `deposit{value: 0}` call will
281
+ * revert otherwise.
282
+ *
283
+ * ## Why no PT/USDC fee deduction?
284
+ *
285
+ * Unlike Scenario 1/2/4 which deduct an operator fee in PT/USDC inside
286
+ * the batch, perp deposit doesn't append a fee transfer because:
287
+ *
288
+ * - User is paying Orderly's LayerZero fee directly via `msg.value`
289
+ * - There's no PAFI-specific operator cost on top — Orderly handles
290
+ * the off-chain accounting once the LayerZero message lands
291
+ *
292
+ * If we want to charge a PAFI service fee on top later, append a
293
+ * `USDC.transfer(feeRecipient, fee)` op — same pattern as the swap
294
+ * builder.
129
295
  */
130
- interface UserOpReceipt {
131
- userOpHash: Hex;
132
- success: boolean;
133
- txHash: Hex;
134
- blockNumber: bigint;
135
- gasUsed: bigint;
136
- /** Effective gas cost paid (wei). */
137
- actualGasCost: bigint;
296
+ interface BuildPerpDepositWithGasDeductionParams {
297
+ /** User EOA (will be `msg.sender` via EIP-7702 delegation). */
298
+ userAddress: Address;
299
+ /** ERC-4337 account nonce — fetched from EntryPoint by the caller. */
300
+ aaNonce: bigint;
301
+ /** Chain ID for Orderly Vault address resolution. */
302
+ chainId: number;
303
+ /**
304
+ * Override Orderly Vault address (e.g. for fork tests). Defaults to
305
+ * `ORDERLY_VAULT_ADDRESSES[chainId]`.
306
+ */
307
+ vaultAddress?: Address;
308
+ /**
309
+ * USDC ERC-20 address — the actual token Orderly accepts. Caller
310
+ * resolves this via `vault.getAllowedToken(TOKEN_HASHES.USDC)` so we
311
+ * don't hardcode the wrong USDC variant (native vs bridged).
312
+ */
313
+ usdcAddress: Address;
314
+ /** USDC amount to deposit (uint128, 6 decimals). */
315
+ amount: bigint;
316
+ /**
317
+ * Pre-built `VaultDepositFE` struct — caller computes accountId via
318
+ * `computeAccountId(user, brokerHash)` and supplies tokenHash.
319
+ */
320
+ depositData: VaultDepositFE;
321
+ /**
322
+ * LayerZero fee in wei — from `vault.getDepositFee(user, data)`.
323
+ * Becomes the `msg.value` on the `deposit()` call. User MUST hold
324
+ * ≥ this much native ETH or the call reverts.
325
+ */
326
+ layerZeroFee: bigint;
327
+ gasLimits?: {
328
+ callGasLimit?: bigint;
329
+ verificationGasLimit?: bigint;
330
+ preVerificationGas?: bigint;
331
+ };
138
332
  }
139
333
  /**
140
- * Sentinel operation value used in tests + docs when `Operation.value`
141
- * is irrelevant (ERC-20 transfers, for example).
334
+ * Build an unsigned UserOp for Scenario 3. Returns a
335
+ * `PartialUserOperation` caller attaches paymaster sponsorship for
336
+ * gas + the user's UserOp-hash signature, then submits to the Bundler.
142
337
  */
143
- declare const ZERO_VALUE = 0n;
338
+ declare function buildPerpDepositWithGasDeduction(params: BuildPerpDepositWithGasDeductionParams): PartialUserOperation;
144
339
 
145
340
  /**
146
341
  * Build an ERC-20 `transfer(to, amount)` operation. Used inside a batch
@@ -344,237 +539,285 @@ interface CheckEthAndBranchParams {
344
539
  declare function checkEthAndBranch(params: CheckEthAndBranchParams): Promise<SubmissionPath>;
345
540
 
346
541
  /**
347
- * ⚠️ MOCK — Relayer v2 `mint()` ABI for the v1.4 sponsored flow.
542
+ * Real `PointToken` ABI matches the contract deployed on Base mainnet
543
+ * (POINT at `0x7d25E7156E51F865D522fd3ef257a6B5DD41b97e`). Sourced from
544
+ * the Solidity contract shipped by the SC team 2026-04-21.
545
+ *
546
+ * ## Mint — two paths
348
547
  *
349
- * Signature guess based on stakeholder memo (`REQUIREMENTS_V2.md §3`):
548
+ * Path 1 Direct (whitelisted minter):
549
+ * mint(address to, uint256 amount)
550
+ * - msg.sender must be in minters[]
551
+ * - Used by off-chain services that hold a minter key
350
552
  *
351
- * mint(
352
- * MintRequest request, // EIP-712 signed by user + issuer
353
- * Signature userSig, // v, r, s
354
- * Signature issuerSig, // v, r, s
355
- * uint256 feeAmount, // PT units to split off to feeRecipient
356
- * address feeRecipient // typically operator or fee collector
357
- * )
553
+ * Path 2 — Sig-gated (gasless, v1.4 sponsored flow):
554
+ * mint(address to, uint256 amount, uint256 deadline, bytes minterSig)
555
+ * - msg.sender MUST equal `to` (the receiver)
556
+ * - minterSig is an EIP-712 MintRequest signature from a whitelisted minter
557
+ * - Consumes `mintRequestNonces[to]`
558
+ * - This is the path v1.4 uses: issuer backend signs, user submits
559
+ * via EIP-7702 + Coinbase Paymaster
358
560
  *
359
- * Behaviour expected:
360
- * - Verify user + issuer EIP-712 signatures against `request`
361
- * - Mint `request.amount` PT to `request.to`
362
- * - Atomic transfer `feeAmount` from `request.to` → `feeRecipient`
363
- * (net mint = `amount - feeAmount`)
364
- * - Increment the on-chain nonce to prevent replay
561
+ * ## Burn — mirror structure
365
562
  *
366
- * When SC team publishes the real ABI, drop it in under
367
- * `src/contracts/real/relayerV2.abi.ts` and flip the export in
368
- * `src/contracts/index.ts` call sites unchanged.
563
+ * Path 1: burn(address from, uint256 amount) whitelisted burner
564
+ * Path 2: burn(address from, uint256 amount, uint256 deadline, bytes burnerSig)
565
+ * msg.sender must equal `from`, burnerSig from whitelisted burner,
566
+ * consumes `burnRequestNonces[from]`
369
567
  *
370
- * See [SC_MOCK_PLAN.md §2.1] for the rationale + swap checklist.
568
+ * Either burn path emits `Transfer(from 0x0)` so BurnIndexer semantics
569
+ * don't depend on which path was taken.
570
+ *
571
+ * ## EIP-712 type hashes (from contract source)
572
+ *
573
+ * MintRequest(address to,uint256 amount,uint256 nonce,uint256 deadline)
574
+ * BurnRequest(address from,uint256 amount,uint256 nonce,uint256 deadline)
575
+ *
576
+ * Domain: EIP-712 standard — name = ERC-20 token name, version = "1",
577
+ * chainId, verifyingContract = this PointToken address.
371
578
  */
372
- declare const MOCK_RELAYER_V2_ABI: readonly [{
579
+ declare const POINT_TOKEN_ABI: readonly [{
373
580
  readonly name: "mint";
374
581
  readonly type: "function";
375
582
  readonly stateMutability: "nonpayable";
376
583
  readonly inputs: readonly [{
377
- readonly type: "tuple";
378
- readonly components: readonly [{
379
- readonly type: "address";
380
- readonly name: "to";
381
- }, {
382
- readonly type: "uint256";
383
- readonly name: "amount";
384
- }, {
385
- readonly type: "uint256";
386
- readonly name: "feeAmount";
387
- }, {
388
- readonly type: "address";
389
- readonly name: "feeRecipient";
390
- }, {
391
- readonly type: "uint256";
392
- readonly name: "nonce";
393
- }, {
394
- readonly type: "uint256";
395
- readonly name: "deadline";
396
- }, {
397
- readonly type: "bytes";
398
- readonly name: "extData";
399
- }];
400
- readonly name: "request";
401
- }, {
402
- readonly type: "tuple";
403
- readonly components: readonly [{
404
- readonly type: "uint8";
405
- readonly name: "v";
406
- }, {
407
- readonly type: "bytes32";
408
- readonly name: "r";
409
- }, {
410
- readonly type: "bytes32";
411
- readonly name: "s";
412
- }];
413
- readonly name: "userSig";
584
+ readonly type: "address";
585
+ readonly name: "to";
414
586
  }, {
415
- readonly type: "tuple";
416
- readonly components: readonly [{
417
- readonly type: "uint8";
418
- readonly name: "v";
419
- }, {
420
- readonly type: "bytes32";
421
- readonly name: "r";
422
- }, {
423
- readonly type: "bytes32";
424
- readonly name: "s";
425
- }];
426
- readonly name: "issuerSig";
587
+ readonly type: "uint256";
588
+ readonly name: "amount";
427
589
  }];
428
590
  readonly outputs: readonly [];
429
591
  }, {
430
- readonly name: "mintRequestNonce";
592
+ readonly name: "mint";
431
593
  readonly type: "function";
432
- readonly stateMutability: "view";
594
+ readonly stateMutability: "nonpayable";
433
595
  readonly inputs: readonly [{
434
596
  readonly type: "address";
435
- readonly name: "user";
597
+ readonly name: "to";
598
+ }, {
599
+ readonly type: "uint256";
600
+ readonly name: "amount";
601
+ }, {
602
+ readonly type: "uint256";
603
+ readonly name: "deadline";
604
+ }, {
605
+ readonly type: "bytes";
606
+ readonly name: "minterSig";
436
607
  }];
437
- readonly outputs: readonly [{
608
+ readonly outputs: readonly [];
609
+ }, {
610
+ readonly name: "burn";
611
+ readonly type: "function";
612
+ readonly stateMutability: "nonpayable";
613
+ readonly inputs: readonly [{
614
+ readonly type: "address";
615
+ readonly name: "from";
616
+ }, {
438
617
  readonly type: "uint256";
618
+ readonly name: "amount";
439
619
  }];
620
+ readonly outputs: readonly [];
440
621
  }, {
441
- readonly name: "Minted";
442
- readonly type: "event";
622
+ readonly name: "burn";
623
+ readonly type: "function";
624
+ readonly stateMutability: "nonpayable";
443
625
  readonly inputs: readonly [{
444
626
  readonly type: "address";
445
- readonly name: "user";
446
- readonly indexed: true;
627
+ readonly name: "from";
447
628
  }, {
448
629
  readonly type: "uint256";
449
630
  readonly name: "amount";
450
631
  }, {
451
632
  readonly type: "uint256";
452
- readonly name: "feeAmount";
633
+ readonly name: "deadline";
453
634
  }, {
635
+ readonly type: "bytes";
636
+ readonly name: "burnerSig";
637
+ }];
638
+ readonly outputs: readonly [];
639
+ }, {
640
+ readonly name: "minters";
641
+ readonly type: "function";
642
+ readonly stateMutability: "view";
643
+ readonly inputs: readonly [{
454
644
  readonly type: "address";
455
- readonly name: "feeRecipient";
456
- readonly indexed: true;
457
- }, {
458
- readonly type: "bytes32";
459
- readonly name: "requestHash";
645
+ readonly name: "account";
460
646
  }];
461
- }];
462
- /**
463
- * Calldata function selector for `mint((...),(...),(...))` as encoded
464
- * by viem against {@link MOCK_RELAYER_V2_ABI}. Callers compare against
465
- * this to sanity-check decoded UserOp inner calls.
466
- *
467
- * Recompute when the real ABI lands — almost certainly differs.
468
- */
469
- declare const MOCK_RELAYER_V2_MINT_SELECTOR: "0xMOCKED__";
470
- /**
471
- * Struct shape that matches {@link MOCK_RELAYER_V2_ABI}. Exported so
472
- * builders can accept a typed input without `as const` gymnastics.
473
- */
474
- interface MockMintRequestV2 {
475
- to: Address;
476
- amount: bigint;
477
- feeAmount: bigint;
478
- feeRecipient: Address;
479
- nonce: bigint;
480
- deadline: bigint;
481
- extData: `0x${string}`;
482
- }
483
- interface MockSignatureStruct {
484
- v: number;
485
- r: `0x${string}`;
486
- s: `0x${string}`;
487
- }
488
-
489
- /**
490
- * ⚠️ MOCK — `PointToken` v1.4 burn surface.
491
- *
492
- * Two variants mocked — SC team will pick ONE before stable; the other
493
- * gets deleted during Phase B swap.
494
- *
495
- * Variant A (simpler, most likely):
496
- * burn(uint256 amount)
497
- * - burns from `msg.sender`
498
- * - caller handles authorization (the user is `msg.sender` via
499
- * EIP-7702 delegation, so `msg.sender == user`)
500
- *
501
- * Variant B (signature-based, if SC prefers explicit consent on-chain):
502
- * burnWithSig(BurnConsent consent, Signature sig)
503
- * - verifies EIP-712 signature before burning
504
- * - used when the caller isn't the user (e.g. a relayer burns on
505
- * behalf of the user)
506
- *
507
- * Either way the ERC-20 emits `Transfer(from, address(0), amount)` so
508
- * `BurnIndexer` semantics don't change.
509
- */
510
- declare const MOCK_POINT_TOKEN_V2_ABI: readonly [{
511
- readonly name: "burn";
647
+ readonly outputs: readonly [{
648
+ readonly type: "bool";
649
+ }];
650
+ }, {
651
+ readonly name: "burners";
652
+ readonly type: "function";
653
+ readonly stateMutability: "view";
654
+ readonly inputs: readonly [{
655
+ readonly type: "address";
656
+ readonly name: "account";
657
+ }];
658
+ readonly outputs: readonly [{
659
+ readonly type: "bool";
660
+ }];
661
+ }, {
662
+ readonly name: "addMinter";
512
663
  readonly type: "function";
513
664
  readonly stateMutability: "nonpayable";
514
665
  readonly inputs: readonly [{
515
- readonly type: "uint256";
516
- readonly name: "amount";
666
+ readonly type: "address";
667
+ readonly name: "minter";
517
668
  }];
518
669
  readonly outputs: readonly [];
519
670
  }, {
520
- readonly name: "burnWithSig";
671
+ readonly name: "removeMinter";
521
672
  readonly type: "function";
522
673
  readonly stateMutability: "nonpayable";
523
674
  readonly inputs: readonly [{
524
- readonly type: "tuple";
525
- readonly components: readonly [{
526
- readonly type: "address";
527
- readonly name: "user";
528
- }, {
529
- readonly type: "address";
530
- readonly name: "pointToken";
531
- }, {
532
- readonly type: "uint256";
533
- readonly name: "amount";
534
- }, {
535
- readonly type: "uint256";
536
- readonly name: "nonce";
537
- }, {
538
- readonly type: "uint256";
539
- readonly name: "deadline";
540
- }];
541
- readonly name: "consent";
542
- }, {
543
- readonly type: "tuple";
544
- readonly components: readonly [{
545
- readonly type: "uint8";
546
- readonly name: "v";
547
- }, {
548
- readonly type: "bytes32";
549
- readonly name: "r";
550
- }, {
551
- readonly type: "bytes32";
552
- readonly name: "s";
553
- }];
554
- readonly name: "sig";
675
+ readonly type: "address";
676
+ readonly name: "minter";
555
677
  }];
556
678
  readonly outputs: readonly [];
557
679
  }, {
558
- readonly name: "balanceOf";
680
+ readonly name: "addBurner";
681
+ readonly type: "function";
682
+ readonly stateMutability: "nonpayable";
683
+ readonly inputs: readonly [{
684
+ readonly type: "address";
685
+ readonly name: "burner";
686
+ }];
687
+ readonly outputs: readonly [];
688
+ }, {
689
+ readonly name: "removeBurner";
690
+ readonly type: "function";
691
+ readonly stateMutability: "nonpayable";
692
+ readonly inputs: readonly [{
693
+ readonly type: "address";
694
+ readonly name: "burner";
695
+ }];
696
+ readonly outputs: readonly [];
697
+ }, {
698
+ readonly name: "mintRequestNonces";
559
699
  readonly type: "function";
560
700
  readonly stateMutability: "view";
561
701
  readonly inputs: readonly [{
562
702
  readonly type: "address";
563
- readonly name: "user";
703
+ readonly name: "receiver";
564
704
  }];
565
705
  readonly outputs: readonly [{
566
706
  readonly type: "uint256";
567
707
  }];
568
708
  }, {
569
- readonly name: "burnNonce";
709
+ readonly name: "burnRequestNonces";
570
710
  readonly type: "function";
571
711
  readonly stateMutability: "view";
572
712
  readonly inputs: readonly [{
573
713
  readonly type: "address";
574
- readonly name: "user";
714
+ readonly name: "from";
715
+ }];
716
+ readonly outputs: readonly [{
717
+ readonly type: "uint256";
718
+ }];
719
+ }, {
720
+ readonly name: "mintingOracle";
721
+ readonly type: "function";
722
+ readonly stateMutability: "view";
723
+ readonly inputs: readonly [];
724
+ readonly outputs: readonly [{
725
+ readonly type: "address";
726
+ }];
727
+ }, {
728
+ readonly name: "setMintingOracle";
729
+ readonly type: "function";
730
+ readonly stateMutability: "nonpayable";
731
+ readonly inputs: readonly [{
732
+ readonly type: "address";
733
+ readonly name: "_mintingOracle";
734
+ }];
735
+ readonly outputs: readonly [];
736
+ }, {
737
+ readonly name: "issuer";
738
+ readonly type: "function";
739
+ readonly stateMutability: "view";
740
+ readonly inputs: readonly [];
741
+ readonly outputs: readonly [{
742
+ readonly type: "address";
743
+ }];
744
+ }, {
745
+ readonly name: "balanceOf";
746
+ readonly type: "function";
747
+ readonly stateMutability: "view";
748
+ readonly inputs: readonly [{
749
+ readonly type: "address";
750
+ readonly name: "account";
751
+ }];
752
+ readonly outputs: readonly [{
753
+ readonly type: "uint256";
754
+ }];
755
+ }, {
756
+ readonly name: "totalSupply";
757
+ readonly type: "function";
758
+ readonly stateMutability: "view";
759
+ readonly inputs: readonly [];
760
+ readonly outputs: readonly [{
761
+ readonly type: "uint256";
762
+ }];
763
+ }, {
764
+ readonly name: "name";
765
+ readonly type: "function";
766
+ readonly stateMutability: "view";
767
+ readonly inputs: readonly [];
768
+ readonly outputs: readonly [{
769
+ readonly type: "string";
770
+ }];
771
+ }, {
772
+ readonly name: "symbol";
773
+ readonly type: "function";
774
+ readonly stateMutability: "view";
775
+ readonly inputs: readonly [];
776
+ readonly outputs: readonly [{
777
+ readonly type: "string";
575
778
  }];
779
+ }, {
780
+ readonly name: "decimals";
781
+ readonly type: "function";
782
+ readonly stateMutability: "view";
783
+ readonly inputs: readonly [];
784
+ readonly outputs: readonly [{
785
+ readonly type: "uint8";
786
+ }];
787
+ }, {
788
+ readonly name: "DOMAIN_SEPARATOR";
789
+ readonly type: "function";
790
+ readonly stateMutability: "view";
791
+ readonly inputs: readonly [];
576
792
  readonly outputs: readonly [{
793
+ readonly type: "bytes32";
794
+ }];
795
+ }, {
796
+ readonly name: "eip712Domain";
797
+ readonly type: "function";
798
+ readonly stateMutability: "view";
799
+ readonly inputs: readonly [];
800
+ readonly outputs: readonly [{
801
+ readonly type: "bytes1";
802
+ readonly name: "fields";
803
+ }, {
804
+ readonly type: "string";
805
+ readonly name: "name";
806
+ }, {
807
+ readonly type: "string";
808
+ readonly name: "version";
809
+ }, {
577
810
  readonly type: "uint256";
811
+ readonly name: "chainId";
812
+ }, {
813
+ readonly type: "address";
814
+ readonly name: "verifyingContract";
815
+ }, {
816
+ readonly type: "bytes32";
817
+ readonly name: "salt";
818
+ }, {
819
+ readonly type: "uint256[]";
820
+ readonly name: "extensions";
578
821
  }];
579
822
  }, {
580
823
  readonly name: "Transfer";
@@ -591,236 +834,360 @@ declare const MOCK_POINT_TOKEN_V2_ABI: readonly [{
591
834
  readonly type: "uint256";
592
835
  readonly name: "value";
593
836
  }];
837
+ }, {
838
+ readonly name: "MinterAdded";
839
+ readonly type: "event";
840
+ readonly inputs: readonly [{
841
+ readonly type: "address";
842
+ readonly name: "minter";
843
+ readonly indexed: true;
844
+ }];
845
+ }, {
846
+ readonly name: "MinterRemoved";
847
+ readonly type: "event";
848
+ readonly inputs: readonly [{
849
+ readonly type: "address";
850
+ readonly name: "minter";
851
+ readonly indexed: true;
852
+ }];
853
+ }, {
854
+ readonly name: "BurnerAdded";
855
+ readonly type: "event";
856
+ readonly inputs: readonly [{
857
+ readonly type: "address";
858
+ readonly name: "burner";
859
+ readonly indexed: true;
860
+ }];
861
+ }, {
862
+ readonly name: "BurnerRemoved";
863
+ readonly type: "event";
864
+ readonly inputs: readonly [{
865
+ readonly type: "address";
866
+ readonly name: "burner";
867
+ readonly indexed: true;
868
+ }];
869
+ }, {
870
+ readonly name: "MintingOracleUpdated";
871
+ readonly type: "event";
872
+ readonly inputs: readonly [{
873
+ readonly type: "address";
874
+ readonly name: "mintingOracle";
875
+ readonly indexed: true;
876
+ }];
594
877
  }];
595
878
 
596
879
  /**
597
- * ⚠️ MOCK placeholder BatchExecutor address.
880
+ * BatchExecutor delegation target addresses.
598
881
  *
599
- * Real deployment:
600
- * - Coinbase may pre-deploy a canonical BatchExecutor that we target
601
- * via EIP-7702 delegation (see blocker B2 in V1.4_V1.5_READINESS.md)
602
- * - Otherwise PAFI deploys a minimal one and publishes the address
882
+ * ## Status
603
883
  *
604
- * The ABI itself (`execute(Call[])`) is stable and lives under
605
- * `../../userop/batchExecute.ts` that's the real one, unchanged
606
- * by the mock swap. Only the **address** is mocked here.
884
+ * Base mainnet: points at **Coinbase Smart Wallet v2**
885
+ * (`0x7702cb554e6bFb442cb743A7dF23154544a7176C`). Coinbase publishes
886
+ * this as the canonical EIP-7702 delegation target on Base every
887
+ * user that wants gas sponsorship via Coinbase Paymaster delegates to
888
+ * this single contract. One contract, all issuers.
607
889
  *
608
- * Pattern: checksum address with hex "DEAD0001" suffix per chain so
609
- * it's obvious in logs which chain is using a mock.
890
+ * Base Sepolia: placeholder; Sepolia is not in active use for PAFI.
891
+ *
892
+ * The ABI (`execute(Call[])`) is exported from
893
+ * `../../userop/batchExecute.ts` and works against the Coinbase
894
+ * contract without change — Coinbase Smart Wallet v2 implements the
895
+ * same call-array signature we already use.
610
896
  */
611
- declare const MOCK_BATCH_EXECUTOR_ADDRESS_BASE_SEPOLIA: Address;
612
- declare const MOCK_BATCH_EXECUTOR_ADDRESS_BASE_MAINNET: Address;
897
+ declare const BATCH_EXECUTOR_ADDRESS_BASE_SEPOLIA: Address;
898
+ declare const BATCH_EXECUTOR_ADDRESS_BASE_MAINNET: Address;
613
899
 
614
900
  /**
615
- * ⚠️ MOCK — per-chain contract addresses for the v1.4 sponsored flow.
901
+ * Per-chain deployed contract addresses v1.4 flow.
902
+ *
903
+ * ## Status (2026-04-22)
616
904
  *
617
- * Real addresses come from SC team once they deploy Relayer v2 and
618
- * pick a BatchExecutor. Until then we use placeholders so the SDK
619
- * code path compiles + tests execute end-to-end.
905
+ * Base mainnet (8453): **all real**. BatchExecutor now points at the
906
+ * canonical Coinbase Smart Wallet v2 contract which PAFI reuses as the
907
+ * EIP-7702 delegation target (no per-app deploy required — one
908
+ * contract, every issuer).
620
909
  *
621
- * **Intentionally not merge-safe to mainnet**callers that resolve
622
- * a mainnet address here get a `0x...DEAD` placeholder which will
623
- * revert at contract-level. That's the point: prod refuses to run
624
- * on mocks.
910
+ * Base Sepolia (84532): entire row is placeholder not in active use.
625
911
  *
626
- * Chain id map:
627
- * - 8453 Base mainnet
628
- * - 84532 Base Sepolia
912
+ * ## What lives where
629
913
  *
630
- * Swap workflow when SC delivers:
631
- * 1. Rename this file `addresses.ts` under `src/contracts/real/`
632
- * 2. Fill real addresses per chain
633
- * 3. Update `src/contracts/index.ts` re-export
634
- * 4. Delete MOCK_* named exports
914
+ * pointToken — live POINT instance (clone of PointToken impl)
915
+ * batchExecutor — EIP-7702 delegation target (Coinbase Smart Wallet v2)
916
+ * usdt — MockERC20 used by Uniswap pools
917
+ * issuerRegistry — registry of all issuers on this chain
918
+ * mintingOracle — per-issuer mint cap enforcer
919
+ * pafiHook — Uniswap V4 hook enforcing the 10% PT→USDT fee
920
+ *
921
+ * PointTokenFactory + PointToken implementation addresses live in
922
+ * separate exports below — they're only needed at provisioning /
923
+ * observability time, not in the hot mint/burn path, so excluded from
924
+ * the per-chain bundle.
635
925
  */
636
926
  interface ContractAddresses {
637
- relayerV2: Address;
638
927
  pointToken: Address;
639
928
  batchExecutor: Address;
640
929
  usdt: Address;
641
930
  issuerRegistry: Address;
642
931
  mintingOracle: Address;
932
+ /**
933
+ * Uniswap V4 hook that enforces the 10% fee on PT→USDT swaps
934
+ * (USDT→PT is free). FE reads this to build `PoolKey.hooks` when
935
+ * constructing a swap; quoters + routers need it to resolve the
936
+ * correct pool.
937
+ */
938
+ pafiHook: Address;
643
939
  }
644
- declare const MOCK_ADDRESSES: Record<number, ContractAddresses>;
940
+ declare const CONTRACT_ADDRESSES: Record<number, ContractAddresses>;
941
+ /**
942
+ * PointTokenFactory address — separate from `ContractAddresses` because
943
+ * it's only used at provisioning time (issuer onboard + token creation),
944
+ * not in the hot mint/burn path.
945
+ */
946
+ declare const POINT_TOKEN_FACTORY_ADDRESSES: Record<number, Address>;
947
+ /**
948
+ * PointToken implementation address — the EIP-1167 clone target used
949
+ * by PointTokenFactory. Exposed for observability / proxy verification;
950
+ * consumers should never call this directly.
951
+ */
952
+ declare const POINT_TOKEN_IMPL_ADDRESSES: Record<number, Address>;
645
953
  /**
646
954
  * Lookup helper — throws if the chain isn't in the map so callers fail
647
955
  * loudly on misconfiguration instead of silently using `undefined`.
648
956
  */
649
- declare function getMockAddresses(chainId: number): ContractAddresses;
957
+ declare function getContractAddresses(chainId: number): ContractAddresses;
650
958
 
651
959
  /**
652
- * ⚠️ MOCK `MintRequest` v2 EIP-712 types.
960
+ * Public contract surface for `@pafi-dev/core/contracts`.
961
+ *
962
+ * Consumers import ABIs + per-chain addresses from this module. EIP-712
963
+ * helpers (`signMintRequest`, `signBurnRequest`, etc.) live under
964
+ * `./eip712/` and are re-exported from the package root — not duplicated
965
+ * here.
653
966
  *
654
- * Extends v0.2.x `MintRequest` (4 fields) with three new fields needed
655
- * for the v1.4 sponsored flow:
967
+ * ## v1.4 flow no Relayer, sig-gated mint/burn
656
968
  *
657
- * + feeAmount PT units taken from the mint for the operator
658
- * + feeRecipient where the fee goes (operator or treasury)
659
- * + extData arbitrary bytes for future extensions (swap path, etc.)
969
+ * Relayer contract dropped. Users call `PointToken.mint(to, amount,
970
+ * deadline, minterSig)` directly via an EIP-7702 delegated UserOp —
971
+ * `msg.sender == user == to`. `minterSig` is an EIP-712 `MintRequest`
972
+ * signed off-chain by the issuer's minter signer (HSM/KMS). Mirror
973
+ * structure on the burn side with `BurnRequest` + `burn(from, amount,
974
+ * deadline, burnerSig)`.
660
975
  *
661
- * When SC team confirms the real struct, drop this file's content into
662
- * the real builder and remove the MOCK_ prefix. The function signatures
663
- * below stay stable only `MOCK_MINT_REQUEST_V2_TYPES` changes.
976
+ * Exports:
977
+ * - `POINT_TOKEN_V2_ABI` — full mint + burn + admin surface
978
+ * - `BATCH_EXECUTOR_*` — EIP-7702 delegation target (ABI real,
979
+ * address still placeholder on all
980
+ * chains until SC delivers)
981
+ * - `CONTRACT_ADDRESSES` — per-chain map (real on 8453 except
982
+ * `batchExecutor` — pending SC)
983
+ * - `POINT_TOKEN_FACTORY_ADDRESSES`, `POINT_TOKEN_IMPL_ADDRESSES`
984
+ * — provisioning / observability helpers
985
+ *
986
+ * Status: all real except BatchExecutor address (single remaining
987
+ * placeholder, flagged inline in `real/addresses.ts`).
664
988
  */
665
- declare const MOCK_MINT_REQUEST_V2_TYPES: {
666
- readonly MintRequest: readonly [{
667
- readonly name: "to";
668
- readonly type: "address";
669
- }, {
670
- readonly name: "amount";
671
- readonly type: "uint256";
672
- }, {
673
- readonly name: "feeAmount";
674
- readonly type: "uint256";
675
- }, {
676
- readonly name: "feeRecipient";
677
- readonly type: "address";
678
- }, {
679
- readonly name: "nonce";
680
- readonly type: "uint256";
681
- }, {
682
- readonly name: "deadline";
683
- readonly type: "uint256";
684
- }, {
685
- readonly name: "extData";
686
- readonly type: "bytes";
687
- }];
688
- };
989
+
689
990
  /**
690
- * Build the typed-data envelope that any EIP-712 signer (viem, ethers,
691
- * Privy) can consume. Callers typically pass the result to
692
- * `walletClient.signTypedData()` or `privy.signTypedData()`.
991
+ * Signature struct kept for consumers that want the tuple form.
992
+ * Most v1.4 paths pass `bytes` (serialized signature) directly to the
993
+ * contract; this struct is only needed if you're manually splitting
994
+ * for other on-chain verifiers.
693
995
  */
694
- declare function buildMockMintRequestV2TypedData(domain: PointTokenDomainConfig, message: MockMintRequestV2): {
695
- domain: {
696
- name: string;
697
- version: "1";
698
- chainId: number;
699
- verifyingContract: `0x${string}`;
700
- };
701
- types: {
702
- readonly MintRequest: readonly [{
703
- readonly name: "to";
704
- readonly type: "address";
705
- }, {
706
- readonly name: "amount";
707
- readonly type: "uint256";
708
- }, {
709
- readonly name: "feeAmount";
710
- readonly type: "uint256";
711
- }, {
712
- readonly name: "feeRecipient";
713
- readonly type: "address";
714
- }, {
715
- readonly name: "nonce";
716
- readonly type: "uint256";
717
- }, {
718
- readonly name: "deadline";
719
- readonly type: "uint256";
720
- }, {
721
- readonly name: "extData";
722
- readonly type: "bytes";
723
- }];
724
- };
725
- primaryType: "MintRequest";
726
- message: MockMintRequestV2;
727
- };
996
+ interface SignatureStruct {
997
+ v: number;
998
+ r: `0x${string}`;
999
+ s: `0x${string}`;
1000
+ }
1001
+
728
1002
  /**
729
- * Sign a `MintRequest` v2 with a viem WalletClient server-side flow
730
- * where the issuer holds the private key directly (KMS-backed signer
731
- * is the production path; see `@pafi-dev/issuer` KMSSignerAdapter).
1003
+ * Options for opening a PAFI Web modal passed through by all adapters.
1004
+ * Web-only fields (width/height/windowName) are ignored by mobile
1005
+ * adapters that can't resize a system in-app browser.
732
1006
  */
733
- declare function signMockMintRequestV2(walletClient: WalletClient, domain: PointTokenDomainConfig, message: MockMintRequestV2): Promise<EIP712Signature>;
1007
+ interface ModalOpenOptions {
1008
+ /** Web popup pixel width. Default 900. Ignored on mobile. */
1009
+ width?: number;
1010
+ /** Web popup pixel height. Default 700. Ignored on mobile. */
1011
+ height?: number;
1012
+ /**
1013
+ * `window.open()` target name. Same name across calls re-uses an
1014
+ * already-open popup. Default: `"pafi-web"`. Web-only.
1015
+ */
1016
+ windowName?: string;
1017
+ /**
1018
+ * Called when the modal closes — either user-initiated (clicked
1019
+ * close, swiped down on mobile) or programmatically via `handle.close()`.
1020
+ */
1021
+ onClose?: () => void;
1022
+ /**
1023
+ * Called when the opened window posts a message back to the parent
1024
+ * via `window.opener.postMessage(data, origin)`. PAFI Web uses this
1025
+ * to signal "swap complete" / "perp deposit complete" back to the
1026
+ * issuer app without needing a redirect.
1027
+ *
1028
+ * `origin` is the posting window's origin — caller MUST verify it
1029
+ * matches the expected PAFI Web host before trusting `data`.
1030
+ */
1031
+ onMessage?: (data: unknown, origin: string) => void;
1032
+ /**
1033
+ * Allowed origins for `onMessage` — messages from other origins are
1034
+ * silently dropped. Pass the PAFI Web host(s), e.g.
1035
+ * `["https://app.pacificfinance.org", "https://app-dev.pacificfinance.org"]`.
1036
+ *
1037
+ * Default: empty (all messages rejected). Set explicitly for security.
1038
+ */
1039
+ allowedOrigins?: string[];
1040
+ }
734
1041
  /**
735
- * Verify a `MintRequest` v2 signature and check it came from the
736
- * expected signer (either user or issuer depending on which side is
737
- * being verified).
1042
+ * Handle to an open PAFI Web modal. Methods are no-ops when the modal
1043
+ * has already closed safe to call without tracking state yourself.
738
1044
  */
739
- declare function verifyMockMintRequestV2(domain: PointTokenDomainConfig, message: MockMintRequestV2, signature: Hex, expectedSigner: Address): Promise<SignatureVerification>;
740
-
1045
+ interface PafiWebModalHandle {
1046
+ /** True when the modal is still open. */
1047
+ readonly isOpen: boolean;
1048
+ /** Close the modal. Fires `onClose` if the callback was supplied. */
1049
+ close(): void;
1050
+ /** Bring the modal to focus (web popup only; mobile ignores). */
1051
+ focus(): void;
1052
+ /**
1053
+ * Post a message INTO the modal — useful for ping/pong handshakes
1054
+ * with PAFI Web. The modal page must be on the same origin or
1055
+ * explicitly listen for the message.
1056
+ */
1057
+ postMessage(data: unknown): void;
1058
+ }
741
1059
  /**
742
- * ⚠️ MOCK `BurnConsent` EIP-712 type for the v1.4 reverse flow.
1060
+ * Adapter that knows how to open a URL in the right UX for the host
1061
+ * platform. Callers register one via `setPafiWebModalAdapter()`; if
1062
+ * none is registered, the core module falls back to `openWebPopup()`
1063
+ * (if `window` is present) or throws (in Node / React Native without
1064
+ * an adapter set).
1065
+ *
1066
+ * ## Mobile adapter example (React Native)
1067
+ *
1068
+ * ```ts
1069
+ * import { setPafiWebModalAdapter } from '@pafi-dev/core';
1070
+ * import InAppBrowser from 'react-native-inappbrowser-reborn';
743
1071
  *
744
- * New type entirely — v0.2.x had no burn-for-credit flow.
1072
+ * setPafiWebModalAdapter({
1073
+ * async open(url, options) {
1074
+ * const result = await InAppBrowser.open(url, {
1075
+ * // iOS: SFSafariViewController
1076
+ * dismissButtonStyle: 'close',
1077
+ * preferredBarTintColor: '#1a1a1a',
1078
+ * preferredControlTintColor: 'white',
1079
+ * // Android: Chrome Custom Tab
1080
+ * toolbarColor: '#1a1a1a',
1081
+ * secondaryToolbarColor: 'black',
1082
+ * });
1083
+ * options?.onClose?.();
1084
+ * return {
1085
+ * isOpen: false,
1086
+ * close: () => InAppBrowser.close(),
1087
+ * focus: () => {},
1088
+ * postMessage: () => {},
1089
+ * };
1090
+ * },
1091
+ * });
1092
+ * ```
745
1093
  *
746
- * User signs `BurnConsent` to authorize burning `amount` PT from their
747
- * wallet in exchange for an off-chain credit of (amount - gasFee).
748
- * Signature is consumed either by:
749
- * - A relayer calling `PointToken.burnWithSig(...)` (Variant B)
750
- * - The paymaster-proxy-sponsored UserOp calling `PointToken.burn(...)`
751
- * with msg.sender = user via EIP-7702 (Variant A)
1094
+ * ## Expo adapter example
752
1095
  *
753
- * Either way the tx emits `Transfer(user → 0x0)` which the issuer's
754
- * `BurnIndexer` watches for and uses to credit the off-chain ledger.
1096
+ * ```ts
1097
+ * import * as WebBrowser from 'expo-web-browser';
755
1098
  *
756
- * Field list is a best-guess — SC team may add fields (e.g. `feeAmount`
757
- * explicit, `extData`). Update this mock when they freeze the spec.
1099
+ * setPafiWebModalAdapter({
1100
+ * async open(url, options) {
1101
+ * await WebBrowser.openBrowserAsync(url);
1102
+ * options?.onClose?.();
1103
+ * return { isOpen: false, close: WebBrowser.dismissBrowser, focus: () => {}, postMessage: () => {} };
1104
+ * },
1105
+ * });
1106
+ * ```
758
1107
  */
759
- interface MockBurnConsent {
760
- user: Address;
761
- pointToken: Address;
762
- amount: bigint;
763
- nonce: bigint;
764
- deadline: bigint;
1108
+ interface PafiWebModalAdapter {
1109
+ open(url: string, options?: ModalOpenOptions): PafiWebModalHandle | Promise<PafiWebModalHandle>;
765
1110
  }
766
- declare const MOCK_BURN_CONSENT_TYPES: {
767
- readonly BurnConsent: readonly [{
768
- readonly name: "user";
769
- readonly type: "address";
770
- }, {
771
- readonly name: "pointToken";
772
- readonly type: "address";
773
- }, {
774
- readonly name: "amount";
775
- readonly type: "uint256";
776
- }, {
777
- readonly name: "nonce";
778
- readonly type: "uint256";
779
- }, {
780
- readonly name: "deadline";
781
- readonly type: "uint256";
782
- }];
783
- };
784
- declare function buildMockBurnConsentTypedData(domain: PointTokenDomainConfig, message: MockBurnConsent): {
785
- domain: {
786
- name: string;
787
- version: "1";
788
- chainId: number;
789
- verifyingContract: `0x${string}`;
790
- };
791
- types: {
792
- readonly BurnConsent: readonly [{
793
- readonly name: "user";
794
- readonly type: "address";
795
- }, {
796
- readonly name: "pointToken";
797
- readonly type: "address";
798
- }, {
799
- readonly name: "amount";
800
- readonly type: "uint256";
801
- }, {
802
- readonly name: "nonce";
803
- readonly type: "uint256";
804
- }, {
805
- readonly name: "deadline";
806
- readonly type: "uint256";
807
- }];
808
- };
809
- primaryType: "BurnConsent";
810
- message: MockBurnConsent;
811
- };
812
- declare function signMockBurnConsent(walletClient: WalletClient, domain: PointTokenDomainConfig, message: MockBurnConsent): Promise<EIP712Signature>;
813
- declare function verifyMockBurnConsent(domain: PointTokenDomainConfig, message: MockBurnConsent, signature: Hex, expectedUser: Address): Promise<SignatureVerification>;
1111
+
1112
+ /**
1113
+ * Web browser popup adapter. Opens the given URL in a centered
1114
+ * `window.open()` popup, polls for close, and optionally forwards
1115
+ * `postMessage` events back to the caller.
1116
+ *
1117
+ * Runtime requirement: `window.open` must exist. Throws if called
1118
+ * under Node / SSR / React Native — use `setPafiWebModalAdapter()` to
1119
+ * provide a platform-specific adapter in those environments.
1120
+ *
1121
+ * ## Popup blocking
1122
+ *
1123
+ * Browsers block `window.open()` unless it happens inside a user
1124
+ * gesture (click handler). Callers MUST wire this into a direct click
1125
+ * handler — wrapping it in a `setTimeout` or async await before the
1126
+ * open call will trigger the blocker.
1127
+ */
1128
+ declare function openWebPopup(url: string, options?: ModalOpenOptions): PafiWebModalHandle;
1129
+ /**
1130
+ * The web popup packaged as a {@link PafiWebModalAdapter} so callers
1131
+ * can register it explicitly (e.g. in a test harness).
1132
+ */
1133
+ declare const webPopupAdapter: PafiWebModalAdapter;
1134
+
1135
+ /**
1136
+ * Register the adapter used by `openPafiWebModal()`. Typically called
1137
+ * once during app initialization — mobile apps register a
1138
+ * SFSafariViewController / Chrome Custom Tabs adapter, desktop apps
1139
+ * can leave it unset (web popup is the default).
1140
+ *
1141
+ * Pass `null` to unregister and fall back to the default.
1142
+ */
1143
+ declare function setPafiWebModalAdapter(adapter: PafiWebModalAdapter | null): void;
1144
+ /**
1145
+ * Return the currently registered adapter, or `null` when none is set.
1146
+ * Useful for tests that want to snapshot-and-restore the adapter.
1147
+ */
1148
+ declare function getPafiWebModalAdapter(): PafiWebModalAdapter | null;
1149
+ /**
1150
+ * Open PAFI Web in the host platform's appropriate UX:
1151
+ *
1152
+ * - Browser (window.open): centered popup, 900×700 by default
1153
+ * - React Native (with adapter registered): SFSafariViewController
1154
+ * / Chrome Custom Tabs via `react-native-inappbrowser-reborn` or
1155
+ * `expo-web-browser`
1156
+ * - Desktop (with adapter registered): custom BrowserWindow / new tab
1157
+ *
1158
+ * Resolution order:
1159
+ * 1. If an adapter was registered via `setPafiWebModalAdapter()`, use it.
1160
+ * 2. Else if `window.open` is available, use the built-in web popup.
1161
+ * 3. Else throw with a clear error pointing at the adapter registry.
1162
+ *
1163
+ * @example
1164
+ * ```ts
1165
+ * // User clicks "Trade on PAFI" button
1166
+ * button.addEventListener('click', async () => {
1167
+ * const modal = await openPafiWebModal('https://app.pacificfinance.org', {
1168
+ * allowedOrigins: ['https://app.pacificfinance.org'],
1169
+ * onMessage: (data, origin) => {
1170
+ * if (typeof data === 'object' && data && 'txHash' in data) {
1171
+ * console.log('Swap confirmed:', data.txHash);
1172
+ * modal.close();
1173
+ * }
1174
+ * },
1175
+ * onClose: () => {
1176
+ * console.log('User closed modal');
1177
+ * },
1178
+ * });
1179
+ * });
1180
+ * ```
1181
+ */
1182
+ declare function openPafiWebModal(url: string, options?: ModalOpenOptions): Promise<PafiWebModalHandle>;
814
1183
 
815
1184
  declare class PafiSDK {
816
1185
  private _pointTokenAddress?;
817
- private _relayContractAddress?;
818
1186
  private _signer?;
819
1187
  private _provider?;
820
1188
  private _chainId?;
821
1189
  constructor(config: PafiSDKConfig);
822
1190
  setPointTokenAddress(address: Address): void;
823
- setRelayContractAddress(address: Address): void;
824
1191
  setSigner(signer: WalletClient): void;
825
1192
  setProvider(provider: PublicClient): void;
826
1193
  private requirePointToken;
@@ -828,10 +1195,6 @@ declare class PafiSDK {
828
1195
  private requireSigner;
829
1196
  private requireChainId;
830
1197
  getDomain(): Promise<PointTokenDomainConfig>;
831
- /**
832
- * Build the EIP-712 typed data for a MintRequest.
833
- * Pass the result to any external signer (Privy, WalletConnect, etc.).
834
- */
835
1198
  buildMintRequestTypedData(message: MintRequest): Promise<{
836
1199
  domain: {
837
1200
  name: string;
@@ -857,10 +1220,6 @@ declare class PafiSDK {
857
1220
  primaryType: "MintRequest";
858
1221
  message: MintRequest;
859
1222
  }>;
860
- /**
861
- * Build the EIP-712 typed data for a ReceiverConsent.
862
- * Pass the result to any external signer (Privy, WalletConnect, etc.).
863
- */
864
1223
  buildReceiverConsentTypedData(message: ReceiverConsent): Promise<{
865
1224
  domain: {
866
1225
  name: string;
@@ -898,11 +1257,6 @@ declare class PafiSDK {
898
1257
  verifyReceiverConsent(message: ReceiverConsent, signature: Hex, expectedReceiver: Address): Promise<SignatureVerification>;
899
1258
  getMintRequestNonce(receiver: Address): Promise<bigint>;
900
1259
  getReceiverConsentNonce(receiver: Address): Promise<bigint>;
901
- encodeMintAndSwap(mint: MintParams, swap: SwapParams): Hex;
902
- decodeMintAndSwap(calldata: Hex): {
903
- mint: MintParams;
904
- swap: SwapParams;
905
- };
906
1260
  /**
907
1261
  * Find the best swap route from `tokenIn` to `tokenOut`.
908
1262
  * Merges `pools` with COMMON_POOLS for the configured chain, builds all
@@ -923,36 +1277,6 @@ declare class PafiSDK {
923
1277
  commands: Hex;
924
1278
  inputs: Hex[];
925
1279
  };
926
- /**
927
- * Build Relay SwapParams + extData from a quote result.
928
- * Returns ready-to-use args for `Relay.mintAndSwap`.
929
- */
930
- buildRelaySwapParams(params: {
931
- quote: {
932
- path: PathKey[];
933
- };
934
- minAmountOut: bigint;
935
- feeInUsdt: bigint;
936
- deadline: bigint;
937
- }): {
938
- swapParams: SwapParams;
939
- extData: Hex;
940
- };
941
- /**
942
- * Encode extData for ReceiverConsent and MintParams.
943
- * extData = abi.encode(minAmountOut, feeInUsdt)
944
- */
945
- encodeExtData(minAmountOut: bigint, feeInUsdt: bigint): Hex;
946
- /**
947
- * Simulate a Relay.mintAndSwap call. Catches reverts (bad signatures,
948
- * expired deadlines, insufficient mint cap, pool errors) before submitting.
949
- *
950
- * @param relayAddress - Relay contract address
951
- * @param mint - MintParams with real signatures
952
- * @param swap - SwapParams (path + deadline)
953
- * @param from - Relayer address that will submit the tx
954
- */
955
- simulateMintAndSwap(relayAddress: Address, mint: MintParams, swap: SwapParams, from: Address): Promise<SimulationResult>;
956
1280
  /**
957
1281
  * Simulate a UniversalRouter.execute swap call. Catches reverts (bad
958
1282
  * approvals, insufficient balance, pool errors) before submitting.
@@ -964,14 +1288,9 @@ declare class PafiSDK {
964
1288
  * @param from - Address that will execute the swap
965
1289
  */
966
1290
  simulateSwap(routerAddress: Address, commands: Hex, inputs: Hex[], deadline: bigint, from: Address): Promise<SwapSimulationResult>;
967
- /**
968
- * Build an EIP-4361 login message for the current signer + chain. The
969
- * caller supplies the issuer-specific fields (domain, nonce, uri); the SDK
970
- * fills in the wallet address and chain id from its own config.
971
- */
972
1291
  createLoginMessage(params: Omit<LoginMessageParams, "address" | "chainId">): Promise<string>;
973
1292
  /** Sign a login message string with the current signer (personal_sign) */
974
1293
  signLoginMessage(message: string): Promise<Hex>;
975
1294
  }
976
1295
 
977
- export { ApiError, BATCH_EXECUTOR_ABI, MOCK_BATCH_EXECUTOR_ADDRESS_BASE_MAINNET as BATCH_EXECUTOR_ADDRESS_BASE_MAINNET, MOCK_BATCH_EXECUTOR_ADDRESS_BASE_SEPOLIA as BATCH_EXECUTOR_ADDRESS_BASE_SEPOLIA, MOCK_BURN_CONSENT_TYPES as BURN_CONSENT_TYPES, BestQuote, type BuildPartialUserOpParams, type MockBurnConsent as BurnConsent, COMMON_POOLS, COMMON_TOKENS, MOCK_ADDRESSES as CONTRACT_ADDRESSES, ChainConfig, type CheckEthAndBranchParams, ConfigurationError, type ContractAddresses, EIP712Signature, ENTRY_POINT_V07, LoginMessageParams, MOCK_MINT_REQUEST_V2_TYPES as MINT_REQUEST_V2_TYPES, MintParams, MintRequest, type MockMintRequestV2 as MintRequestV2, type Operation, POINT_TOKEN_POOLS, MOCK_POINT_TOKEN_V2_ABI as POINT_TOKEN_V2_ABI, PafiSDK, PafiSDKConfig, PafiSDKError, type PartialUserOperation, PathKey, type PaymasterConfig, type PaymasterFields, PointTokenDomainConfig, PoolKey, QuoteResult, MOCK_RELAYER_V2_ABI as RELAYER_V2_ABI, MOCK_RELAYER_V2_MINT_SELECTOR as RELAYER_V2_MINT_SELECTOR, ReceiverConsent, SUPPORTED_CHAINS, type MockSignatureStruct as SignatureStruct, SignatureVerification, SigningError, SimulationError, SimulationResult, type SponsorshipScenario, type SubmissionPath, SwapParams, SwapSimulationResult, UNIVERSAL_ROUTER_ADDRESSES, type UserOpReceipt, type UserOperation, V4_QUOTER_ADDRESSES, ZERO_VALUE, _resetPaymasterConfigForTests, assembleUserOperation, buildMockBurnConsentTypedData as buildBurnConsentTypedData, buildMockMintRequestV2TypedData as buildMintRequestV2TypedData, buildPartialUserOperation, checkEthAndBranch, encodeBatchExecute, erc20ApproveOp, erc20BurnOp, erc20TransferOp, getMockAddresses as getContractAddresses, getPaymasterConfig, isPaymasterConfigured, mintRequestTypes, rawCallOp, receiverConsentTypes, setPaymasterConfig, signMockBurnConsent as signBurnConsent, signMockMintRequestV2 as signMintRequestV2, verifyMockBurnConsent as verifyBurnConsent, verifyMockMintRequestV2 as verifyMintRequestV2 };
1296
+ export { ApiError, BATCH_EXECUTOR_ABI, BATCH_EXECUTOR_ADDRESS_BASE_MAINNET, BATCH_EXECUTOR_ADDRESS_BASE_SEPOLIA, BROKER_HASHES, BestQuote, type BuildPartialUserOpParams, type BuildPerpDepositWithGasDeductionParams, COMMON_POOLS, COMMON_TOKENS, CONTRACT_ADDRESSES, ChainConfig, type CheckEthAndBranchParams, ConfigurationError, type ContractAddresses, EIP712Signature, LoginMessageParams, MintRequest, type ModalOpenOptions, ORDERLY_VAULT_ABI, ORDERLY_VAULT_ADDRESSES, ORDERLY_VAULT_BASE_MAINNET, Operation, POINT_TOKEN_FACTORY_ADDRESSES, POINT_TOKEN_IMPL_ADDRESSES, POINT_TOKEN_POOLS, POINT_TOKEN_ABI as POINT_TOKEN_V2_ABI, PafiSDK, PafiSDKConfig, PafiSDKError, type PafiWebModalAdapter, type PafiWebModalHandle, PartialUserOperation, type PaymasterConfig, PointTokenDomainConfig, PoolKey, QuoteResult, ReceiverConsent, SUPPORTED_CHAINS, type SignatureStruct, SignatureVerification, SigningError, SimulationError, type SponsorshipScenario, type SubmissionPath, SwapSimulationResult, TOKEN_HASHES, UNIVERSAL_ROUTER_ADDRESSES, UserOperation, V4_QUOTER_ADDRESSES, type VaultDepositFE, _resetPaymasterConfigForTests, assembleUserOperation, buildPartialUserOperation, buildPerpDepositWithGasDeduction, burnRequestTypes, checkEthAndBranch, computeAccountId, encodeBatchExecute, erc20ApproveOp, erc20BurnOp, erc20TransferOp, getContractAddresses, getPafiWebModalAdapter, getPaymasterConfig, isPaymasterConfigured, mintRequestTypes, openPafiWebModal, openWebPopup, rawCallOp, receiverConsentTypes, setPafiWebModalAdapter, setPaymasterConfig, webPopupAdapter };