@pafi-dev/core 0.3.0-beta.8 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +99 -1118
- package/dist/auth/index.cjs +16 -2
- package/dist/auth/index.cjs.map +1 -1
- package/dist/auth/index.d.cts +93 -2
- package/dist/auth/index.d.ts +93 -2
- package/dist/auth/index.js +17 -3
- package/dist/{chunk-W23EJNYG.js → chunk-543IPI6E.js} +11 -3
- package/dist/chunk-543IPI6E.js.map +1 -0
- package/dist/{chunk-GWLEEXM4.cjs → chunk-FNJZUNK3.cjs} +90 -2
- package/dist/chunk-FNJZUNK3.cjs.map +1 -0
- package/dist/{chunk-EDR5SFJN.cjs → chunk-TYIEMGMY.cjs} +10 -2
- package/dist/chunk-TYIEMGMY.cjs.map +1 -0
- package/dist/{chunk-O4SMTUOY.js → chunk-W6VULMCO.js} +90 -2
- package/dist/chunk-W6VULMCO.js.map +1 -0
- package/dist/{index-B06IJlHe.d.ts → index-C1FGQ004.d.ts} +22 -33
- package/dist/{index-B7pGBych.d.cts → index-CzBaRIqs.d.cts} +22 -33
- package/dist/index.cjs +114 -110
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +154 -174
- package/dist/index.d.ts +154 -174
- package/dist/index.js +99 -95
- package/dist/index.js.map +1 -1
- package/dist/swap/index.cjs +2 -2
- package/dist/swap/index.d.cts +1 -1
- package/dist/swap/index.d.ts +1 -1
- package/dist/swap/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-EDR5SFJN.cjs.map +0 -1
- package/dist/chunk-GWLEEXM4.cjs.map +0 -1
- package/dist/chunk-O4SMTUOY.js.map +0 -1
- package/dist/chunk-W23EJNYG.js.map +0 -1
package/dist/auth/index.cjs
CHANGED
|
@@ -2,10 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var _chunkGWLEEXM4cjs = require('../chunk-GWLEEXM4.cjs');
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
var _chunkFNJZUNK3cjs = require('../chunk-FNJZUNK3.cjs');
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
exports.SPONSOR_AUTH_DOMAIN_NAME = _chunkFNJZUNK3cjs.SPONSOR_AUTH_DOMAIN_NAME; exports.SPONSOR_AUTH_TYPES = _chunkFNJZUNK3cjs.SPONSOR_AUTH_TYPES; exports.buildSponsorAuthDomain = _chunkFNJZUNK3cjs.buildSponsorAuthDomain; exports.buildSponsorAuthTypedData = _chunkFNJZUNK3cjs.buildSponsorAuthTypedData; exports.computeCallDataHash = _chunkFNJZUNK3cjs.computeCallDataHash; exports.createLoginMessage = _chunkFNJZUNK3cjs.createLoginMessage; exports.parseLoginMessage = _chunkFNJZUNK3cjs.parseLoginMessage; exports.signSponsorAuth = _chunkFNJZUNK3cjs.signSponsorAuth; exports.verifyLoginMessage = _chunkFNJZUNK3cjs.verifyLoginMessage; exports.verifySponsorAuth = _chunkFNJZUNK3cjs.verifySponsorAuth;
|
|
11
25
|
//# sourceMappingURL=index.cjs.map
|
package/dist/auth/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/phitran/Pacific-Finance/pafi-backend/pafi-sdk/packages/core/dist/auth/index.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACF,yDAA8B;AAC9B;AACE;AACA;AACA;AACF,
|
|
1
|
+
{"version":3,"sources":["/Users/phitran/Pacific-Finance/pafi-backend/pafi-sdk/packages/core/dist/auth/index.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,urBAAC","file":"/Users/phitran/Pacific-Finance/pafi-backend/pafi-sdk/packages/core/dist/auth/index.cjs"}
|
package/dist/auth/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Address, Hex } from 'viem';
|
|
1
|
+
import { Address, Hex, WalletClient } from 'viem';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Parameters for building an EIP-4361 (Sign-In with Ethereum) login message.
|
|
@@ -57,4 +57,95 @@ declare function parseLoginMessage(message: string): LoginMessageParams;
|
|
|
57
57
|
*/
|
|
58
58
|
declare function verifyLoginMessage(message: string, signature: Hex): Promise<VerifyLoginResult>;
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
declare const SPONSOR_AUTH_DOMAIN_NAME = "PafiSponsorAuth";
|
|
61
|
+
declare const SPONSOR_AUTH_TYPES: {
|
|
62
|
+
readonly SponsorAuth: readonly [{
|
|
63
|
+
readonly name: "chainId";
|
|
64
|
+
readonly type: "uint256";
|
|
65
|
+
}, {
|
|
66
|
+
readonly name: "sender";
|
|
67
|
+
readonly type: "address";
|
|
68
|
+
}, {
|
|
69
|
+
readonly name: "callDataHash";
|
|
70
|
+
readonly type: "bytes32";
|
|
71
|
+
}, {
|
|
72
|
+
readonly name: "nonce";
|
|
73
|
+
readonly type: "uint256";
|
|
74
|
+
}, {
|
|
75
|
+
readonly name: "expiresAt";
|
|
76
|
+
readonly type: "uint256";
|
|
77
|
+
}, {
|
|
78
|
+
readonly name: "scenario";
|
|
79
|
+
readonly type: "string";
|
|
80
|
+
}, {
|
|
81
|
+
readonly name: "issuerId";
|
|
82
|
+
readonly type: "string";
|
|
83
|
+
}];
|
|
84
|
+
};
|
|
85
|
+
interface SponsorAuthPayload {
|
|
86
|
+
chainId: number;
|
|
87
|
+
sender: Address;
|
|
88
|
+
callDataHash: Hex;
|
|
89
|
+
nonce: bigint;
|
|
90
|
+
expiresAt: number;
|
|
91
|
+
scenario: string;
|
|
92
|
+
issuerId: string;
|
|
93
|
+
}
|
|
94
|
+
interface SponsorAuthVerifyResult {
|
|
95
|
+
ok: boolean;
|
|
96
|
+
recoveredAddress?: Address;
|
|
97
|
+
reason?: "EXPIRED" | "INVALID_SIGNER" | "INVALID_SIGNATURE_FORMAT";
|
|
98
|
+
}
|
|
99
|
+
declare function buildSponsorAuthDomain(chainId: number): {
|
|
100
|
+
name: string;
|
|
101
|
+
version: string;
|
|
102
|
+
chainId: number;
|
|
103
|
+
verifyingContract: Address;
|
|
104
|
+
};
|
|
105
|
+
declare function buildSponsorAuthTypedData(payload: SponsorAuthPayload): {
|
|
106
|
+
domain: {
|
|
107
|
+
name: string;
|
|
108
|
+
version: string;
|
|
109
|
+
chainId: number;
|
|
110
|
+
verifyingContract: Address;
|
|
111
|
+
};
|
|
112
|
+
types: {
|
|
113
|
+
readonly SponsorAuth: readonly [{
|
|
114
|
+
readonly name: "chainId";
|
|
115
|
+
readonly type: "uint256";
|
|
116
|
+
}, {
|
|
117
|
+
readonly name: "sender";
|
|
118
|
+
readonly type: "address";
|
|
119
|
+
}, {
|
|
120
|
+
readonly name: "callDataHash";
|
|
121
|
+
readonly type: "bytes32";
|
|
122
|
+
}, {
|
|
123
|
+
readonly name: "nonce";
|
|
124
|
+
readonly type: "uint256";
|
|
125
|
+
}, {
|
|
126
|
+
readonly name: "expiresAt";
|
|
127
|
+
readonly type: "uint256";
|
|
128
|
+
}, {
|
|
129
|
+
readonly name: "scenario";
|
|
130
|
+
readonly type: "string";
|
|
131
|
+
}, {
|
|
132
|
+
readonly name: "issuerId";
|
|
133
|
+
readonly type: "string";
|
|
134
|
+
}];
|
|
135
|
+
};
|
|
136
|
+
primaryType: "SponsorAuth";
|
|
137
|
+
message: {
|
|
138
|
+
chainId: bigint;
|
|
139
|
+
sender: `0x${string}`;
|
|
140
|
+
callDataHash: `0x${string}`;
|
|
141
|
+
nonce: bigint;
|
|
142
|
+
expiresAt: bigint;
|
|
143
|
+
scenario: string;
|
|
144
|
+
issuerId: string;
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
declare function computeCallDataHash(callData: Hex): Hex;
|
|
148
|
+
declare function signSponsorAuth(wallet: WalletClient, payload: SponsorAuthPayload): Promise<Hex>;
|
|
149
|
+
declare function verifySponsorAuth(payload: SponsorAuthPayload, signature: Hex, expectedSigner: Address): Promise<SponsorAuthVerifyResult>;
|
|
150
|
+
|
|
151
|
+
export { type LoginMessageParams, SPONSOR_AUTH_DOMAIN_NAME, SPONSOR_AUTH_TYPES, type SponsorAuthPayload, type SponsorAuthVerifyResult, type VerifyLoginResult, buildSponsorAuthDomain, buildSponsorAuthTypedData, computeCallDataHash, createLoginMessage, parseLoginMessage, signSponsorAuth, verifyLoginMessage, verifySponsorAuth };
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Address, Hex } from 'viem';
|
|
1
|
+
import { Address, Hex, WalletClient } from 'viem';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Parameters for building an EIP-4361 (Sign-In with Ethereum) login message.
|
|
@@ -57,4 +57,95 @@ declare function parseLoginMessage(message: string): LoginMessageParams;
|
|
|
57
57
|
*/
|
|
58
58
|
declare function verifyLoginMessage(message: string, signature: Hex): Promise<VerifyLoginResult>;
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
declare const SPONSOR_AUTH_DOMAIN_NAME = "PafiSponsorAuth";
|
|
61
|
+
declare const SPONSOR_AUTH_TYPES: {
|
|
62
|
+
readonly SponsorAuth: readonly [{
|
|
63
|
+
readonly name: "chainId";
|
|
64
|
+
readonly type: "uint256";
|
|
65
|
+
}, {
|
|
66
|
+
readonly name: "sender";
|
|
67
|
+
readonly type: "address";
|
|
68
|
+
}, {
|
|
69
|
+
readonly name: "callDataHash";
|
|
70
|
+
readonly type: "bytes32";
|
|
71
|
+
}, {
|
|
72
|
+
readonly name: "nonce";
|
|
73
|
+
readonly type: "uint256";
|
|
74
|
+
}, {
|
|
75
|
+
readonly name: "expiresAt";
|
|
76
|
+
readonly type: "uint256";
|
|
77
|
+
}, {
|
|
78
|
+
readonly name: "scenario";
|
|
79
|
+
readonly type: "string";
|
|
80
|
+
}, {
|
|
81
|
+
readonly name: "issuerId";
|
|
82
|
+
readonly type: "string";
|
|
83
|
+
}];
|
|
84
|
+
};
|
|
85
|
+
interface SponsorAuthPayload {
|
|
86
|
+
chainId: number;
|
|
87
|
+
sender: Address;
|
|
88
|
+
callDataHash: Hex;
|
|
89
|
+
nonce: bigint;
|
|
90
|
+
expiresAt: number;
|
|
91
|
+
scenario: string;
|
|
92
|
+
issuerId: string;
|
|
93
|
+
}
|
|
94
|
+
interface SponsorAuthVerifyResult {
|
|
95
|
+
ok: boolean;
|
|
96
|
+
recoveredAddress?: Address;
|
|
97
|
+
reason?: "EXPIRED" | "INVALID_SIGNER" | "INVALID_SIGNATURE_FORMAT";
|
|
98
|
+
}
|
|
99
|
+
declare function buildSponsorAuthDomain(chainId: number): {
|
|
100
|
+
name: string;
|
|
101
|
+
version: string;
|
|
102
|
+
chainId: number;
|
|
103
|
+
verifyingContract: Address;
|
|
104
|
+
};
|
|
105
|
+
declare function buildSponsorAuthTypedData(payload: SponsorAuthPayload): {
|
|
106
|
+
domain: {
|
|
107
|
+
name: string;
|
|
108
|
+
version: string;
|
|
109
|
+
chainId: number;
|
|
110
|
+
verifyingContract: Address;
|
|
111
|
+
};
|
|
112
|
+
types: {
|
|
113
|
+
readonly SponsorAuth: readonly [{
|
|
114
|
+
readonly name: "chainId";
|
|
115
|
+
readonly type: "uint256";
|
|
116
|
+
}, {
|
|
117
|
+
readonly name: "sender";
|
|
118
|
+
readonly type: "address";
|
|
119
|
+
}, {
|
|
120
|
+
readonly name: "callDataHash";
|
|
121
|
+
readonly type: "bytes32";
|
|
122
|
+
}, {
|
|
123
|
+
readonly name: "nonce";
|
|
124
|
+
readonly type: "uint256";
|
|
125
|
+
}, {
|
|
126
|
+
readonly name: "expiresAt";
|
|
127
|
+
readonly type: "uint256";
|
|
128
|
+
}, {
|
|
129
|
+
readonly name: "scenario";
|
|
130
|
+
readonly type: "string";
|
|
131
|
+
}, {
|
|
132
|
+
readonly name: "issuerId";
|
|
133
|
+
readonly type: "string";
|
|
134
|
+
}];
|
|
135
|
+
};
|
|
136
|
+
primaryType: "SponsorAuth";
|
|
137
|
+
message: {
|
|
138
|
+
chainId: bigint;
|
|
139
|
+
sender: `0x${string}`;
|
|
140
|
+
callDataHash: `0x${string}`;
|
|
141
|
+
nonce: bigint;
|
|
142
|
+
expiresAt: bigint;
|
|
143
|
+
scenario: string;
|
|
144
|
+
issuerId: string;
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
declare function computeCallDataHash(callData: Hex): Hex;
|
|
148
|
+
declare function signSponsorAuth(wallet: WalletClient, payload: SponsorAuthPayload): Promise<Hex>;
|
|
149
|
+
declare function verifySponsorAuth(payload: SponsorAuthPayload, signature: Hex, expectedSigner: Address): Promise<SponsorAuthVerifyResult>;
|
|
150
|
+
|
|
151
|
+
export { type LoginMessageParams, SPONSOR_AUTH_DOMAIN_NAME, SPONSOR_AUTH_TYPES, type SponsorAuthPayload, type SponsorAuthVerifyResult, type VerifyLoginResult, buildSponsorAuthDomain, buildSponsorAuthTypedData, computeCallDataHash, createLoginMessage, parseLoginMessage, signSponsorAuth, verifyLoginMessage, verifySponsorAuth };
|
package/dist/auth/index.js
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
|
+
SPONSOR_AUTH_DOMAIN_NAME,
|
|
3
|
+
SPONSOR_AUTH_TYPES,
|
|
4
|
+
buildSponsorAuthDomain,
|
|
5
|
+
buildSponsorAuthTypedData,
|
|
6
|
+
computeCallDataHash,
|
|
2
7
|
createLoginMessage,
|
|
3
8
|
parseLoginMessage,
|
|
4
|
-
|
|
5
|
-
|
|
9
|
+
signSponsorAuth,
|
|
10
|
+
verifyLoginMessage,
|
|
11
|
+
verifySponsorAuth
|
|
12
|
+
} from "../chunk-W6VULMCO.js";
|
|
6
13
|
export {
|
|
14
|
+
SPONSOR_AUTH_DOMAIN_NAME,
|
|
15
|
+
SPONSOR_AUTH_TYPES,
|
|
16
|
+
buildSponsorAuthDomain,
|
|
17
|
+
buildSponsorAuthTypedData,
|
|
18
|
+
computeCallDataHash,
|
|
7
19
|
createLoginMessage,
|
|
8
20
|
parseLoginMessage,
|
|
9
|
-
|
|
21
|
+
signSponsorAuth,
|
|
22
|
+
verifyLoginMessage,
|
|
23
|
+
verifySponsorAuth
|
|
10
24
|
};
|
|
11
25
|
//# sourceMappingURL=index.js.map
|
|
@@ -169,7 +169,7 @@ async function simulateSwap(client, routerAddress, commands, inputs, deadline, f
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
// src/swap/buildSwapWithGasDeduction.ts
|
|
172
|
-
import { encodeFunctionData as encodeFunctionData4 } from "viem";
|
|
172
|
+
import { encodeFunctionData as encodeFunctionData4, getAddress } from "viem";
|
|
173
173
|
|
|
174
174
|
// src/userop/batchExecute.ts
|
|
175
175
|
import { encodeFunctionData as encodeFunctionData2, parseAbi } from "viem";
|
|
@@ -261,6 +261,7 @@ function rawCallOp(target, data, value = 0n) {
|
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
// src/swap/buildSwapWithGasDeduction.ts
|
|
264
|
+
var PERMIT2_ADDRESS = getAddress("0x000000000022d473030f116ddee9f6b43ac78ba3");
|
|
264
265
|
function buildSwapWithGasDeduction(params) {
|
|
265
266
|
if (params.amountIn <= 0n) {
|
|
266
267
|
throw new Error("buildSwapWithGasDeduction: amountIn must be positive");
|
|
@@ -292,12 +293,19 @@ function buildSwapWithGasDeduction(params) {
|
|
|
292
293
|
functionName: "execute",
|
|
293
294
|
args: [commands, inputs, params.deadline]
|
|
294
295
|
});
|
|
296
|
+
const permit2ApproveData = buildPermit2ApprovalCalldata(
|
|
297
|
+
params.pointTokenAddress,
|
|
298
|
+
params.universalRouterAddress,
|
|
299
|
+
params.amountIn,
|
|
300
|
+
Number(params.deadline)
|
|
301
|
+
);
|
|
295
302
|
const operations = [
|
|
296
303
|
erc20ApproveOp(
|
|
297
304
|
params.pointTokenAddress,
|
|
298
|
-
|
|
305
|
+
PERMIT2_ADDRESS,
|
|
299
306
|
params.amountIn
|
|
300
307
|
),
|
|
308
|
+
rawCallOp(PERMIT2_ADDRESS, permit2ApproveData),
|
|
301
309
|
rawCallOp(params.universalRouterAddress, swapCallData)
|
|
302
310
|
];
|
|
303
311
|
if (params.gasFeePt > 0n) {
|
|
@@ -348,4 +356,4 @@ export {
|
|
|
348
356
|
rawCallOp,
|
|
349
357
|
buildSwapWithGasDeduction
|
|
350
358
|
};
|
|
351
|
-
//# sourceMappingURL=chunk-
|
|
359
|
+
//# sourceMappingURL=chunk-543IPI6E.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/swap/approval.ts","../src/swap/universalRouter.ts","../src/errors.ts","../src/swap/simulate.ts","../src/swap/buildSwapWithGasDeduction.ts","../src/userop/batchExecute.ts","../src/userop/buildUserOperation.ts","../src/userop/operations.ts"],"sourcesContent":["import { encodeFunctionData } from \"viem\";\nimport type { Address, Hex, PublicClient } from \"viem\";\nimport { erc20Abi } from \"../abi/erc20\";\nimport { permit2Abi } from \"../abi/permit2\";\n\nexport async function checkAllowance(\n client: PublicClient,\n token: Address,\n owner: Address,\n spender: Address,\n): Promise<bigint> {\n return client.readContract({\n address: token,\n abi: erc20Abi,\n functionName: \"allowance\",\n args: [owner, spender],\n });\n}\n\n/**\n * Encode an ERC-20 approve(spender, amount) call.\n */\nexport function buildErc20ApprovalCalldata(\n spender: Address,\n amount: bigint,\n): Hex {\n return encodeFunctionData({\n abi: erc20Abi,\n functionName: \"approve\",\n args: [spender, amount],\n });\n}\n\n/**\n * Encode a Permit2 approve(token, spender, amount, expiration) call.\n */\nexport function buildPermit2ApprovalCalldata(\n token: Address,\n spender: Address,\n amount: bigint,\n expiration: number,\n): Hex {\n return encodeFunctionData({\n abi: permit2Abi,\n functionName: \"approve\",\n args: [token, spender, amount, expiration],\n });\n}\n","import { encodeAbiParameters, encodePacked } from \"viem\";\nimport type { Address, Hex } from \"viem\";\nimport type { PathKey, QuoteResult } from \"../types\";\n\n// -------------------------------------------------------------------------\n// V4 UniversalRouter command / action constants\n// Reference: https://github.com/Uniswap/v4-periphery/blob/main/src/libraries/Actions.sol\n// -------------------------------------------------------------------------\n\n/** UniversalRouter command byte for V4 swap */\nexport const V4_SWAP = 0x10 as const;\n\n/** V4 actions */\nexport const SWAP_EXACT_IN_SINGLE = 0x06 as const;\nexport const SWAP_EXACT_IN = 0x07 as const;\nexport const SETTLE_ALL = 0x0c as const;\nexport const TAKE_ALL = 0x0f as const;\n\n// -------------------------------------------------------------------------\n// ABI type strings matching Uniswap's V4Planner encoding\n// Reference: https://github.com/Uniswap/sdks/blob/main/sdks/v4-sdk/src/utils/v4Planner.ts\n//\n// IMPORTANT: PathKey.fee is uint256 in the V4 Router ABI (not uint24).\n// -------------------------------------------------------------------------\n\n// PathKey components for V4 Router ABI encoding.\n// IMPORTANT: fee is uint256 in the V4 Router (not uint24 as in PoolKey).\n// Reference: https://github.com/Uniswap/sdks/blob/main/sdks/v4-sdk/src/utils/v4Planner.ts\nconst PATH_KEY_ABI_COMPONENTS = [\n { name: \"intermediateCurrency\", type: \"address\" },\n { name: \"fee\", type: \"uint256\" },\n { name: \"tickSpacing\", type: \"int24\" },\n { name: \"hooks\", type: \"address\" },\n { name: \"hookData\", type: \"bytes\" },\n] as const;\n\nconst EXACT_INPUT_PARAMS_ABI = [\n { name: \"currencyIn\", type: \"address\" },\n {\n name: \"path\",\n type: \"tuple[]\",\n components: PATH_KEY_ABI_COMPONENTS,\n },\n { name: \"amountIn\", type: \"uint128\" },\n { name: \"amountOutMinimum\", type: \"uint128\" },\n] as const;\n\n/**\n * Build the calldata inputs[0] (the V4_SWAP command payload) for\n * UniversalRouter.execute.\n *\n * Actions encoded: SWAP_EXACT_IN → SETTLE_ALL → TAKE_ALL\n *\n * Encoding matches the Uniswap V4 SDK's V4Planner — each action's params\n * are individually ABI-encoded, then wrapped together with the action bytes.\n */\nexport function buildV4SwapInput(\n currencyIn: Address,\n path: PathKey[],\n amountIn: bigint,\n minAmountOut: bigint,\n outputCurrency: Address,\n): Hex {\n const actions = encodePacked(\n [\"uint8\", \"uint8\", \"uint8\"],\n [SWAP_EXACT_IN, SETTLE_ALL, TAKE_ALL],\n );\n\n // Param 0: ExactInputParams — encoded as a single tuple so the CalldataDecoder\n // can locate it via a single offset pointer. fee is uint256 per V4 Router spec.\n const swapParam = encodeAbiParameters(\n [{ name: \"swap\", type: \"tuple\", components: EXACT_INPUT_PARAMS_ABI }],\n [\n {\n currencyIn,\n path: path.map((p) => ({\n intermediateCurrency: p.intermediateCurrency,\n fee: BigInt(p.fee),\n tickSpacing: p.tickSpacing,\n hooks: p.hooks,\n hookData: p.hookData,\n })),\n amountIn,\n amountOutMinimum: minAmountOut,\n },\n ],\n );\n\n // Param 1: SETTLE_ALL { currency, maxAmount }\n const settleParam = encodeAbiParameters(\n [\n { name: \"currency\", type: \"address\" },\n { name: \"maxAmount\", type: \"uint256\" },\n ],\n [currencyIn, amountIn],\n );\n\n // Param 2: TAKE_ALL { currency, minAmount }\n const takeParam = encodeAbiParameters(\n [\n { name: \"currency\", type: \"address\" },\n { name: \"minAmount\", type: \"uint256\" },\n ],\n [outputCurrency, minAmountOut],\n );\n\n return encodeAbiParameters(\n [\n { name: \"actions\", type: \"bytes\" },\n { name: \"params\", type: \"bytes[]\" },\n ],\n [actions, [swapParam, settleParam, takeParam]],\n );\n}\n\n/**\n * Build the full commands + inputs args for UniversalRouter.execute.\n */\nexport function buildUniversalRouterExecuteArgs(\n currencyIn: Address,\n path: PathKey[],\n amountIn: bigint,\n minAmountOut: bigint,\n outputCurrency: Address,\n): { commands: Hex; inputs: Hex[] } {\n const commands = encodePacked([\"uint8\"], [V4_SWAP]);\n const inputs: Hex[] = [\n buildV4SwapInput(currencyIn, path, amountIn, minAmountOut, outputCurrency),\n ];\n return { commands, inputs };\n}\n\n/**\n * Build UniversalRouter execute args from a quote result.\n *\n * Takes the output of `findBestQuote` / `quoteBestRoute` and produces\n * ready-to-use `{ commands, inputs }` for `UniversalRouter.execute`.\n *\n * @param quote - Quote result containing the path\n * @param currencyIn - Input token address\n * @param currencyOut - Output token address\n * @param amountIn - Exact input amount (same value passed to the quoter)\n * @param minAmountOut - Minimum acceptable output (caller applies slippage)\n *\n * @deprecated Since v1.4 — the Issuer App no longer handles swaps.\n * For the new PT→USDT batch call on PAFI Web (Scenario 4 with\n * EIP-7702 gas deduction), use `buildSwapWithGasDeduction()` (v1.5).\n * This helper is kept for legacy v0.2.x consumers; will be removed in v2.0.\n */\nexport function buildSwapFromQuote(params: {\n quote: QuoteResult;\n currencyIn: Address;\n currencyOut: Address;\n amountIn: bigint;\n minAmountOut: bigint;\n}): { commands: Hex; inputs: Hex[] } {\n return buildUniversalRouterExecuteArgs(\n params.currencyIn,\n params.quote.path,\n params.amountIn,\n params.minAmountOut,\n params.currencyOut,\n );\n}\n","export class PafiSDKError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PafiSDKError\";\n }\n}\n\nexport class ConfigurationError extends PafiSDKError {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigurationError\";\n }\n}\n\nexport class SigningError extends PafiSDKError {\n constructor(message: string) {\n super(message);\n this.name = \"SigningError\";\n }\n}\n\nexport class SimulationError extends PafiSDKError {\n constructor(\n public operation: string,\n public reason: string,\n ) {\n super(`Simulation failed for ${operation}: ${reason}`);\n this.name = \"SimulationError\";\n }\n}\n\nexport class ApiError extends PafiSDKError {\n constructor(\n message: string,\n public status?: number,\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n","import type { Address, Hex, PublicClient } from \"viem\";\nimport { universalRouterAbi } from \"../abi/universalRouter\";\nimport { SimulationError } from \"../errors\";\n\nexport interface SwapSimulationResult {\n success: boolean;\n gasEstimate: bigint;\n}\n\n/**\n * Simulate a UniversalRouter.execute swap call via eth_call (no gas spent).\n *\n * Runs the full V4 swap flow — token transfer via Permit2, swap via\n * PoolManager, output settlement — without submitting a transaction.\n * If the simulation reverts, throws a `SimulationError` with the reason.\n *\n * @param client - viem PublicClient\n * @param routerAddress - UniversalRouter contract address\n * @param commands - Packed command bytes (from buildSwapFromQuote)\n * @param inputs - Encoded inputs per command (from buildSwapFromQuote)\n * @param deadline - Unix timestamp after which the tx expires\n * @param from - Address that will execute the swap\n */\nexport async function simulateSwap(\n client: PublicClient,\n routerAddress: Address,\n commands: Hex,\n inputs: Hex[],\n deadline: bigint,\n from: Address,\n): Promise<SwapSimulationResult> {\n try {\n const gasEstimate = await client.estimateContractGas({\n address: routerAddress,\n abi: universalRouterAbi,\n functionName: \"execute\",\n args: [commands, inputs, deadline],\n account: from,\n });\n\n return { success: true, gasEstimate };\n } catch (error: unknown) {\n const message =\n error instanceof Error ? error.message : \"Unknown simulation error\";\n throw new SimulationError(\"swap\", message);\n }\n}\n","import { encodeFunctionData, getAddress } from \"viem\";\nimport type { Address, Hex } from \"viem\";\nimport { universalRouterAbi } from \"../abi/universalRouter\";\nimport type { PathKey } from \"../types\";\nimport { buildPartialUserOperation } from \"../userop/buildUserOperation\";\nimport type { PartialUserOperation } from \"../userop/types\";\nimport {\n erc20ApproveOp,\n erc20TransferOp,\n rawCallOp,\n} from \"../userop/operations\";\nimport type { Operation } from \"../userop/types\";\nimport { buildUniversalRouterExecuteArgs } from \"./universalRouter\";\nimport { buildPermit2ApprovalCalldata } from \"./approval\";\n\n// Permit2 address used by the PAFI UniversalRouter on Base mainnet.\n// NOTE: This is NOT the canonical Permit2 (0x...c2ccca1d). The PAFI router\n// embeds 0x000000000022d473030f116ddee9f6b43ac78ba3 — verified from bytecode.\nconst PERMIT2_ADDRESS = getAddress(\"0x000000000022d473030f116ddee9f6b43ac78ba3\");\n\n/**\n * v1.5 — Scenario 4: Swap PT → USDT on PAFI Web with gas fee\n * deducted in PT from the user's balance.\n *\n * Builds an unsigned `PartialUserOperation` that packages up to four\n * inner calls into a single `BatchExecutor.execute(calls[])`:\n *\n * 1. `PT.approve(Permit2, amountIn)` — grant Permit2 ERC-20 allowance\n * 2. `Permit2.approve(PT, router, amountIn, deadline)` — authorize\n * the UniversalRouter to pull PT via Permit2\n * 3. `UniversalRouter.execute(commands, inputs, deadline)` — V4 swap\n * PT → USDT; user receives ≥ `minAmountOut` USDT\n * 4. `PT.transfer(feeRecipient, gasFeePt)` — pay the operator back\n * for sponsoring the gas, in PT (omitted when `gasFeePt` is 0)\n *\n * The user's wallet must hold `amountIn + gasFeePt` PT before the\n * UserOp runs. All inner calls execute atomically via EIP-7702\n * delegation (`msg.sender = user`), so a reverting swap unwinds\n * the approvals and fee transfer too.\n *\n * ## Fee model\n *\n * The gas fee is a separate `transfer` after the swap — it does NOT\n * come out of the USDT output, because that output goes straight to\n * the user's wallet with no intermediate hook.\n *\n * If the FE wants \"user receives exactly X USDT after gas\":\n * 1. Quote PT→USDT for candidate `amountIn` values\n * 2. Pick an `amountIn` where `minAmountOut ≈ X`\n * 3. Separately compute `gasFeePt` from the operator's rate\n * 4. Ensure user's PT balance ≥ `amountIn + gasFeePt`\n *\n * ## Order of operations\n *\n * Fee transfer is last so a reverting swap also refunds the fee\n * (atomic batch revert semantics).\n */\nexport interface BuildSwapWithGasDeductionParams {\n /** User's EOA (with EIP-7702 delegation to BatchExecutor). */\n userAddress: Address;\n /** ERC-4337 account nonce — fetched from EntryPoint by the caller. */\n aaNonce: bigint;\n\n /** PT token address being swapped. */\n pointTokenAddress: Address;\n /** Destination currency (typically USDT). */\n outputTokenAddress: Address;\n /** UniversalRouter contract address (chain-specific). */\n universalRouterAddress: Address;\n\n /** PT units to swap. User's balance must be ≥ `amountIn + gasFeePt`. */\n amountIn: bigint;\n /**\n * Minimum USDT to accept out of the swap. Caller applies slippage\n * (typically ~0.5-1%) against a fresh quote. Sub-minimum swap reverts.\n */\n minAmountOut: bigint;\n\n /** V4 pool path for the swap. Single-hop = 1 PathKey. */\n swapPath: PathKey[];\n /** Unix seconds. After this, the router rejects the swap. */\n deadline: bigint;\n\n /** PT amount transferred to `feeRecipient` as gas fee recovery. */\n gasFeePt: bigint;\n /** Where the gas fee lands — typically the operator or fee collector. */\n feeRecipient: Address;\n\n /** Override ERC-4337 gas estimates. Defaults are conservative; tune down for cheaper UserOps. */\n gasLimits?: {\n callGasLimit?: bigint;\n verificationGasLimit?: bigint;\n preVerificationGas?: bigint;\n };\n}\n\n/**\n * Build an unsigned UserOp for Scenario 4. Returns a\n * `PartialUserOperation` — caller attaches paymaster sponsorship (via\n * `POST /api/paymaster/sponsor`), adds the user's UserOp-hash\n * signature, and submits to the Bundler.\n *\n * @throws when `amountIn` or `gasFeePt` is not positive, or when\n * `swapPath` is empty (at least one PathKey required).\n */\nexport function buildSwapWithGasDeduction(\n params: BuildSwapWithGasDeductionParams,\n): PartialUserOperation {\n if (params.amountIn <= 0n) {\n throw new Error(\"buildSwapWithGasDeduction: amountIn must be positive\");\n }\n if (params.minAmountOut < 0n) {\n throw new Error(\n \"buildSwapWithGasDeduction: minAmountOut must be non-negative\",\n );\n }\n if (params.gasFeePt < 0n) {\n throw new Error(\n \"buildSwapWithGasDeduction: gasFeePt must be non-negative\",\n );\n }\n if (params.swapPath.length === 0) {\n throw new Error(\n \"buildSwapWithGasDeduction: swapPath must contain at least one PathKey\",\n );\n }\n\n const { commands, inputs } = buildUniversalRouterExecuteArgs(\n params.pointTokenAddress,\n params.swapPath,\n params.amountIn,\n params.minAmountOut,\n params.outputTokenAddress,\n );\n\n const swapCallData: Hex = encodeFunctionData({\n abi: universalRouterAbi,\n functionName: \"execute\",\n args: [commands, inputs, params.deadline],\n });\n\n const permit2ApproveData: Hex = buildPermit2ApprovalCalldata(\n params.pointTokenAddress,\n params.universalRouterAddress,\n params.amountIn,\n Number(params.deadline),\n );\n\n const operations: Operation[] = [\n erc20ApproveOp(\n params.pointTokenAddress,\n PERMIT2_ADDRESS,\n params.amountIn,\n ),\n rawCallOp(PERMIT2_ADDRESS, permit2ApproveData),\n rawCallOp(params.universalRouterAddress, swapCallData),\n ];\n\n if (params.gasFeePt > 0n) {\n operations.push(\n erc20TransferOp(\n params.pointTokenAddress,\n params.feeRecipient,\n params.gasFeePt,\n ),\n );\n }\n\n return buildPartialUserOperation({\n sender: params.userAddress,\n nonce: params.aaNonce,\n operations,\n gasLimits: {\n callGasLimit: params.gasLimits?.callGasLimit ?? 700_000n,\n verificationGasLimit:\n params.gasLimits?.verificationGasLimit ?? 150_000n,\n preVerificationGas: params.gasLimits?.preVerificationGas ?? 50_000n,\n },\n });\n}\n","import { encodeFunctionData, parseAbi } from \"viem\";\nimport type { Hex } from \"viem\";\nimport type { Operation } from \"./types\";\n\n/**\n * Standard BatchExecutor ABI — a contract that takes an array of calls\n * and invokes each one in sequence, reverting all if any fail.\n *\n * Compatible with OpenZeppelin `Account.execute(Call[])`, Biconomy\n * `executeBatch`, Safe `MultiSend`, and most EIP-7702 delegation\n * targets. The exact deployed address is supplied by the infra team\n * (see [V1.4_V1.5_READINESS.md B2]).\n */\nexport const BATCH_EXECUTOR_ABI = parseAbi([\n \"function execute((address target, uint256 value, bytes data)[] calls)\",\n]);\n\n/**\n * Encode a batch of operations into calldata for `BatchExecutor.execute()`.\n * The resulting calldata goes into `UserOperation.callData`.\n *\n * When the EOA has an EIP-7702 delegation to a BatchExecutor, calling\n * this calldata against the EOA runs all operations with\n * `msg.sender = EOA` for each inner call.\n *\n * @param operations batch of calls, in execution order\n * @returns calldata bytes for `execute((address,uint256,bytes)[])`\n */\nexport function encodeBatchExecute(operations: Operation[]): Hex {\n if (operations.length === 0) {\n throw new Error(\"encodeBatchExecute: operations array must not be empty\");\n }\n return encodeFunctionData({\n abi: BATCH_EXECUTOR_ABI,\n functionName: \"execute\",\n args: [\n operations.map((op) => ({\n target: op.target,\n value: op.value,\n data: op.data,\n })),\n ],\n });\n}\n","import type { Address } from \"viem\";\nimport type { Operation, PartialUserOperation, UserOperation } from \"./types\";\nimport { encodeBatchExecute } from \"./batchExecute\";\n\n/**\n * Default gas limits — rough upper bounds for a 2-op batch on Base.\n * Bundler re-estimates before submission, so these are only used when\n * the caller doesn't supply their own.\n */\nconst DEFAULT_CALL_GAS_LIMIT = 500_000n;\nconst DEFAULT_VERIFICATION_GAS_LIMIT = 150_000n;\nconst DEFAULT_PRE_VERIFICATION_GAS = 50_000n;\n\nexport interface BuildPartialUserOpParams {\n /** User's EOA (with EIP-7702 delegation). */\n sender: Address;\n /** Batch of operations — encoded into callData via `encodeBatchExecute`. */\n operations: Operation[];\n /** EntryPoint nonce for this sender. Caller fetches from the EntryPoint contract. */\n nonce: bigint;\n /** Optional gas overrides; bundler re-estimates before submission. */\n gasLimits?: {\n callGasLimit?: bigint;\n verificationGasLimit?: bigint;\n preVerificationGas?: bigint;\n };\n /** Optional fee overrides; bundler usually fills these. */\n feeOverrides?: {\n maxFeePerGas?: bigint;\n maxPriorityFeePerGas?: bigint;\n };\n}\n\n/**\n * Build a partial ERC-4337 UserOperation from a batch of operations.\n * Paymaster fields and signature are populated later:\n * 1. Call `PafiBackendClient.requestSponsorship()` → get paymaster fields\n * 2. Compute userOpHash and have the user sign it (via Privy)\n * 3. Attach `signature` → submit to bundler\n *\n * This function is a pure struct builder — no network calls.\n */\nexport function buildPartialUserOperation(\n params: BuildPartialUserOpParams,\n): PartialUserOperation {\n return {\n sender: params.sender,\n nonce: params.nonce,\n callData: encodeBatchExecute(params.operations),\n callGasLimit: params.gasLimits?.callGasLimit ?? DEFAULT_CALL_GAS_LIMIT,\n verificationGasLimit:\n params.gasLimits?.verificationGasLimit ??\n DEFAULT_VERIFICATION_GAS_LIMIT,\n preVerificationGas:\n params.gasLimits?.preVerificationGas ?? DEFAULT_PRE_VERIFICATION_GAS,\n maxFeePerGas: params.feeOverrides?.maxFeePerGas ?? 0n,\n maxPriorityFeePerGas: params.feeOverrides?.maxPriorityFeePerGas ?? 0n,\n };\n}\n\n/**\n * Assemble a full UserOperation once paymaster fields + signature are\n * known. Used after `PafiBackendClient.requestSponsorship()` and user\n * signing complete.\n */\nexport function assembleUserOperation(\n partial: PartialUserOperation,\n paymaster: {\n paymaster: Address;\n paymasterData: `0x${string}`;\n paymasterVerificationGasLimit: bigint;\n paymasterPostOpGasLimit: bigint;\n },\n signature: `0x${string}`,\n): UserOperation {\n return {\n ...partial,\n paymaster: paymaster.paymaster,\n paymasterData: paymaster.paymasterData,\n paymasterVerificationGasLimit: paymaster.paymasterVerificationGasLimit,\n paymasterPostOpGasLimit: paymaster.paymasterPostOpGasLimit,\n signature,\n };\n}\n","import { encodeFunctionData, erc20Abi, parseAbi } from \"viem\";\nimport type { Address } from \"viem\";\nimport type { Operation } from \"./types\";\n\n/**\n * ERC20Burnable extension — `burn(uint256 amount)` burns from msg.sender.\n * The EOA (via EIP-7702 delegation) is the `msg.sender` when a batch\n * runs — so this burns the user's balance without any role check.\n */\nconst ERC20_BURNABLE_ABI = parseAbi([\"function burn(uint256 amount)\"]);\n\n/**\n * Build an ERC-20 `transfer(to, amount)` operation. Used inside a batch\n * to move fee tokens from the user to the fee recipient atomically with\n * the main action.\n */\nexport function erc20TransferOp(\n token: Address,\n to: Address,\n amount: bigint,\n): Operation {\n return {\n target: token,\n value: 0n,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"transfer\",\n args: [to, amount],\n }),\n };\n}\n\n/**\n * Build an ERC-20 `approve(spender, amount)` operation. Used inside a\n * batch before a swap / deposit call so the AMM / protocol can pull\n * tokens from the user.\n */\nexport function erc20ApproveOp(\n token: Address,\n spender: Address,\n amount: bigint,\n): Operation {\n return {\n target: token,\n value: 0n,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"approve\",\n args: [spender, amount],\n }),\n };\n}\n\n/**\n * Build an ERC-20 `burn(amount)` operation (OpenZeppelin ERC20Burnable\n * extension). Burns from `msg.sender`, which — via EIP-7702 — is the\n * user's EOA.\n *\n * Requires the PointToken contract to expose a public `burn(uint256)`\n * without a role check. See\n * [SDK_V1.4_TASKS.md §11 — PointToken.burn callable via batch].\n */\nexport function erc20BurnOp(token: Address, amount: bigint): Operation {\n return {\n target: token,\n value: 0n,\n data: encodeFunctionData({\n abi: ERC20_BURNABLE_ABI,\n functionName: \"burn\",\n args: [amount],\n }),\n };\n}\n\n/**\n * Build a raw call operation with caller-supplied calldata. Useful for\n * non-ERC-20 contracts (PoolManager.swap, PerpDEX.deposit, Relayer.mint)\n * where the encoding is specific to that protocol.\n */\nexport function rawCallOp(\n target: Address,\n data: `0x${string}`,\n value: bigint = 0n,\n): Operation {\n return { target, value, data };\n}\n"],"mappings":"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","names":["encodeFunctionData","encodeFunctionData","encodeFunctionData","erc20Abi","parseAbi","encodeFunctionData"]}
|
|
@@ -155,9 +155,97 @@ function optionalDate(fields, key) {
|
|
|
155
155
|
return new Date(raw);
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
// src/auth/sponsorAuth.ts
|
|
159
|
+
|
|
160
|
+
var SPONSOR_AUTH_DOMAIN_NAME = "PafiSponsorAuth";
|
|
161
|
+
var SPONSOR_AUTH_TYPES = {
|
|
162
|
+
SponsorAuth: [
|
|
163
|
+
{ name: "chainId", type: "uint256" },
|
|
164
|
+
{ name: "sender", type: "address" },
|
|
165
|
+
{ name: "callDataHash", type: "bytes32" },
|
|
166
|
+
{ name: "nonce", type: "uint256" },
|
|
167
|
+
{ name: "expiresAt", type: "uint256" },
|
|
168
|
+
{ name: "scenario", type: "string" },
|
|
169
|
+
{ name: "issuerId", type: "string" }
|
|
170
|
+
]
|
|
171
|
+
};
|
|
172
|
+
function buildSponsorAuthDomain(chainId) {
|
|
173
|
+
return {
|
|
174
|
+
name: SPONSOR_AUTH_DOMAIN_NAME,
|
|
175
|
+
version: "1",
|
|
176
|
+
chainId,
|
|
177
|
+
verifyingContract: "0x0000000000000000000000000000000000000000"
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function buildMessage(payload) {
|
|
181
|
+
return {
|
|
182
|
+
chainId: BigInt(payload.chainId),
|
|
183
|
+
sender: payload.sender,
|
|
184
|
+
callDataHash: payload.callDataHash,
|
|
185
|
+
nonce: payload.nonce,
|
|
186
|
+
expiresAt: BigInt(payload.expiresAt),
|
|
187
|
+
scenario: payload.scenario,
|
|
188
|
+
issuerId: payload.issuerId
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function buildSponsorAuthTypedData(payload) {
|
|
192
|
+
return {
|
|
193
|
+
domain: buildSponsorAuthDomain(payload.chainId),
|
|
194
|
+
types: SPONSOR_AUTH_TYPES,
|
|
195
|
+
primaryType: "SponsorAuth",
|
|
196
|
+
message: buildMessage(payload)
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function computeCallDataHash(callData) {
|
|
200
|
+
return _viem.keccak256.call(void 0, callData);
|
|
201
|
+
}
|
|
202
|
+
async function signSponsorAuth(wallet, payload) {
|
|
203
|
+
const { domain, types, primaryType, message } = buildSponsorAuthTypedData(payload);
|
|
204
|
+
return wallet.signTypedData({
|
|
205
|
+
account: wallet.account,
|
|
206
|
+
domain,
|
|
207
|
+
types,
|
|
208
|
+
primaryType,
|
|
209
|
+
message
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
async function verifySponsorAuth(payload, signature, expectedSigner) {
|
|
213
|
+
const nowSec = Math.floor(Date.now() / 1e3);
|
|
214
|
+
if (payload.expiresAt < nowSec) {
|
|
215
|
+
return { ok: false, reason: "EXPIRED" };
|
|
216
|
+
}
|
|
217
|
+
if (signature.length < 132) {
|
|
218
|
+
return { ok: false, reason: "INVALID_SIGNATURE_FORMAT" };
|
|
219
|
+
}
|
|
220
|
+
let recovered;
|
|
221
|
+
try {
|
|
222
|
+
const { domain, types, primaryType, message } = buildSponsorAuthTypedData(payload);
|
|
223
|
+
recovered = await _viem.recoverTypedDataAddress.call(void 0, {
|
|
224
|
+
domain,
|
|
225
|
+
types,
|
|
226
|
+
primaryType,
|
|
227
|
+
message,
|
|
228
|
+
signature
|
|
229
|
+
});
|
|
230
|
+
} catch (e) {
|
|
231
|
+
return { ok: false, reason: "INVALID_SIGNATURE_FORMAT" };
|
|
232
|
+
}
|
|
233
|
+
if (recovered.toLowerCase() !== expectedSigner.toLowerCase()) {
|
|
234
|
+
return { ok: false, reason: "INVALID_SIGNER", recoveredAddress: recovered };
|
|
235
|
+
}
|
|
236
|
+
return { ok: true, recoveredAddress: recovered };
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
158
246
|
|
|
159
247
|
|
|
160
248
|
|
|
161
249
|
|
|
162
|
-
exports.createLoginMessage = createLoginMessage; exports.parseLoginMessage = parseLoginMessage; exports.verifyLoginMessage = verifyLoginMessage;
|
|
163
|
-
//# sourceMappingURL=chunk-
|
|
250
|
+
exports.createLoginMessage = createLoginMessage; exports.parseLoginMessage = parseLoginMessage; exports.verifyLoginMessage = verifyLoginMessage; exports.SPONSOR_AUTH_DOMAIN_NAME = SPONSOR_AUTH_DOMAIN_NAME; exports.SPONSOR_AUTH_TYPES = SPONSOR_AUTH_TYPES; exports.buildSponsorAuthDomain = buildSponsorAuthDomain; exports.buildSponsorAuthTypedData = buildSponsorAuthTypedData; exports.computeCallDataHash = computeCallDataHash; exports.signSponsorAuth = signSponsorAuth; exports.verifySponsorAuth = verifySponsorAuth;
|
|
251
|
+
//# sourceMappingURL=chunk-FNJZUNK3.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/phitran/Pacific-Finance/pafi-backend/pafi-sdk/packages/core/dist/chunk-FNJZUNK3.cjs","../src/auth/loginMessage.ts","../src/auth/sponsorAuth.ts"],"names":[],"mappings":"AAAA;ACAA,4BAAiE;AAIjE,IAAM,gBAAA,EAAkB,GAAA;AACxB,IAAM,kBAAA,EAAoB,gCAAA;AASnB,SAAS,kBAAA,CAAmB,MAAA,EAAoC;AACrE,EAAA,MAAM;AAAA,IACJ,MAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,GAAA;AAAA,IACA,UAAA,EAAY,iBAAA;AAAA,IACZ,QAAA,EAAU,eAAA;AAAA,IACV,SAAA,kBAAW,IAAI,IAAA,CAAK,CAAA;AAAA,IACpB,cAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,EACF,EAAA,EAAI,MAAA;AAEJ,EAAA,GAAA,CAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,KAAA,CAAM,qCAAqC,CAAA;AAClE,EAAA,GAAA,CAAI,CAAC,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,oCAAoC,CAAA;AAChE,EAAA,GAAA,CAAI,CAAC,GAAA,EAAK,MAAM,IAAI,KAAA,CAAM,kCAAkC,CAAA;AAE5D,EAAA,MAAM,YAAA,EAAc,8BAAA,OAAkB,CAAA;AAEtC,EAAA,MAAM,MAAA,EAAkB,CAAC,CAAA;AACzB,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA;AACA,EAAA;AACA,EAAA;AACP,EAAA;AACI,IAAA;AACA,IAAA;AACR,EAAA;AACW,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACP,EAAA;AACI,IAAA;AACR,EAAA;AACI,EAAA;AACI,IAAA;AACR,EAAA;AACI,EAAA;AACI,IAAA;AACR,EAAA;AAEO,EAAA;AACT;AAOgB;AACR,EAAA;AACI,EAAA;AACE,IAAA;AACZ,EAAA;AAEM,EAAA;AACA,EAAA;AACJ,IAAA;AACF,EAAA;AACK,EAAA;AACO,IAAA;AACZ,EAAA;AACM,EAAA;AAEA,EAAA;AACD,EAAA;AACO,IAAA;AACZ,EAAA;AACM,EAAA;AAGF,EAAA;AACM,EAAA;AACE,IAAA;AACZ,EAAA;AACA,EAAA;AAEI,EAAA;AAEA,EAAA;AACF,IAAA;AACA,IAAA;AACU,IAAA;AACF,MAAA;AACR,IAAA;AACA,IAAA;AACF,EAAA;AAEM,EAAA;AACC,EAAA;AACC,IAAA;AACF,IAAA;AACE,IAAA;AACF,IAAA;AACI,MAAA;AACR,IAAA;AACM,IAAA;AACA,IAAA;AACC,IAAA;AACT,EAAA;AAEY,EAAA;AACN,EAAA;AACA,EAAA;AACM,EAAA;AACA,IAAA;AACZ,EAAA;AACM,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AAEA,EAAA;AACJ,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACI,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACG,EAAA;AACT;AAQA;AAIQ,EAAA;AACA,EAAA;AACK,IAAA;AACT,IAAA;AACA,IAAA;AACD,EAAA;AACU,EAAA;AACA,IAAA;AACX,EAAA;AAEM,EAAA;AACG,EAAA;AACX;AAMM;AACJ,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACD;AAEQ;AACK,EAAA;AACA,EAAA;AACL,EAAA;AACT;AAES;AACD,EAAA;AACF,EAAA;AACQ,IAAA;AACZ,EAAA;AACO,EAAA;AACT;AAES;AAIK,EAAA;AACA,EAAA;AACD,EAAA;AACb;ADlDc;AACA;AE7JL;AAGI;AAEA;AACX,EAAA;AACU,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACV,EAAA;AACF;AAkBgB;AACP,EAAA;AACC,IAAA;AACG,IAAA;AACT,IAAA;AACA,IAAA;AACF,EAAA;AACF;AAES;AACA,EAAA;AACI,IAAA;AACD,IAAA;AACR,IAAA;AACO,IAAA;AACP,IAAA;AACU,IAAA;AACA,IAAA;AACZ,EAAA;AACF;AAEgB;AACP,EAAA;AACG,IAAA;AACD,IAAA;AACP,IAAA;AACS,IAAA;AACX,EAAA;AACF;AAEgB;AACP,EAAA;AACT;AAEA;AAIU,EAAA;AAED,EAAA;AACI,IAAA;AACT,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACD,EAAA;AACH;AAEA;AAKQ,EAAA;AACM,EAAA;AACD,IAAA;AACX,EAAA;AAEI,EAAA;AACO,IAAA;AACX,EAAA;AAEI,EAAA;AACA,EAAA;AACM,IAAA;AAER,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACD,IAAA;AACK,EAAA;AACG,IAAA;AACX,EAAA;AAEI,EAAA;AACO,IAAA;AACX,EAAA;AAES,EAAA;AACX;AFyHc;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/Users/phitran/Pacific-Finance/pafi-backend/pafi-sdk/packages/core/dist/chunk-FNJZUNK3.cjs","sourcesContent":[null,"import { getAddress, verifyMessage, recoverMessageAddress } from \"viem\";\nimport type { Address, Hex } from \"viem\";\nimport type { LoginMessageParams, VerifyLoginResult } from \"./types\";\n\nconst DEFAULT_VERSION = \"1\";\nconst DEFAULT_STATEMENT = \"Sign in with Ethereum to PAFI.\";\n\n/**\n * Build an EIP-4361 login message string.\n *\n * The output is a deterministic plain-text message that the wallet signs via\n * `personal_sign`. The same message can be parsed back with\n * {@link parseLoginMessage} and verified with {@link verifyLoginMessage}.\n */\nexport function createLoginMessage(params: LoginMessageParams): string {\n const {\n domain,\n address,\n chainId,\n nonce,\n uri,\n statement = DEFAULT_STATEMENT,\n version = DEFAULT_VERSION,\n issuedAt = new Date(),\n expirationTime,\n notBefore,\n requestId,\n } = params;\n\n if (!domain) throw new Error(\"createLoginMessage: domain required\");\n if (!nonce) throw new Error(\"createLoginMessage: nonce required\");\n if (!uri) throw new Error(\"createLoginMessage: uri required\");\n\n const checksummed = getAddress(address);\n\n const lines: string[] = [];\n lines.push(`${domain} wants you to sign in with your Ethereum account:`);\n lines.push(checksummed);\n lines.push(\"\");\n if (statement) {\n lines.push(statement);\n lines.push(\"\");\n }\n lines.push(`URI: ${uri}`);\n lines.push(`Version: ${version}`);\n lines.push(`Chain ID: ${chainId}`);\n lines.push(`Nonce: ${nonce}`);\n lines.push(`Issued At: ${issuedAt.toISOString()}`);\n if (expirationTime) {\n lines.push(`Expiration Time: ${expirationTime.toISOString()}`);\n }\n if (notBefore) {\n lines.push(`Not Before: ${notBefore.toISOString()}`);\n }\n if (requestId) {\n lines.push(`Request ID: ${requestId}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Parse a login message string built by {@link createLoginMessage} back into\n * its structured fields. Throws if the message does not match the expected\n * EIP-4361 layout.\n */\nexport function parseLoginMessage(message: string): LoginMessageParams {\n const lines = message.split(\"\\n\");\n if (lines.length < 7) {\n throw new Error(\"parseLoginMessage: message too short\");\n }\n\n const headerLine = lines[0] ?? \"\";\n const headerMatch = headerLine.match(\n /^(?<domain>.+) wants you to sign in with your Ethereum account:$/,\n );\n if (!headerMatch || !headerMatch.groups) {\n throw new Error(\"parseLoginMessage: invalid header line\");\n }\n const domain = headerMatch.groups[\"domain\"]!;\n\n const addressLine = lines[1] ?? \"\";\n if (!/^0x[0-9a-fA-F]{40}$/.test(addressLine)) {\n throw new Error(\"parseLoginMessage: invalid address line\");\n }\n const address = getAddress(addressLine);\n\n // After address: blank line, optional statement + blank line, then key:value lines.\n let cursor = 2;\n if (lines[cursor] !== \"\") {\n throw new Error(\"parseLoginMessage: missing blank line after address\");\n }\n cursor++;\n\n let statement: string | undefined;\n // Statement is present if the next line is not a known key.\n if (cursor < lines.length && !looksLikeKeyValue(lines[cursor]!)) {\n statement = lines[cursor];\n cursor++;\n if (lines[cursor] !== \"\") {\n throw new Error(\"parseLoginMessage: missing blank line after statement\");\n }\n cursor++;\n }\n\n const fields = new Map<string, string>();\n for (; cursor < lines.length; cursor++) {\n const line = lines[cursor]!;\n if (line === \"\") continue;\n const idx = line.indexOf(\": \");\n if (idx === -1) {\n throw new Error(`parseLoginMessage: malformed field line: \"${line}\"`);\n }\n const key = line.slice(0, idx);\n const value = line.slice(idx + 2);\n fields.set(key, value);\n }\n\n const uri = requireField(fields, \"URI\");\n const version = requireField(fields, \"Version\");\n const chainId = Number(requireField(fields, \"Chain ID\"));\n if (!Number.isInteger(chainId)) {\n throw new Error(\"parseLoginMessage: Chain ID is not an integer\");\n }\n const nonce = requireField(fields, \"Nonce\");\n const issuedAt = new Date(requireField(fields, \"Issued At\"));\n const expirationTime = optionalDate(fields, \"Expiration Time\");\n const notBefore = optionalDate(fields, \"Not Before\");\n const requestId = fields.get(\"Request ID\");\n\n const result: LoginMessageParams = {\n domain,\n address,\n chainId,\n nonce,\n uri,\n version,\n issuedAt,\n };\n if (statement !== undefined) result.statement = statement;\n if (expirationTime !== undefined) result.expirationTime = expirationTime;\n if (notBefore !== undefined) result.notBefore = notBefore;\n if (requestId !== undefined) result.requestId = requestId;\n return result;\n}\n\n/**\n * Verify that a login message was signed by the address embedded in the\n * message. Returns `{ valid, address }` where `address` is the recovered\n * signer (checksummed). Does NOT check expiration / not-before / nonce\n * consumption — those are the AuthService's responsibility.\n */\nexport async function verifyLoginMessage(\n message: string,\n signature: Hex,\n): Promise<VerifyLoginResult> {\n const parsed = parseLoginMessage(message);\n const valid = await verifyMessage({\n address: parsed.address,\n message,\n signature,\n });\n if (valid) {\n return { valid: true, address: parsed.address };\n }\n // Recover anyway so callers can log the mismatch.\n const recovered = await recoverMessageAddress({ message, signature });\n return { valid: false, address: getAddress(recovered) as Address };\n}\n\n// -------------------------------------------------------------------------\n// helpers\n// -------------------------------------------------------------------------\n\nconst KNOWN_KEYS = new Set([\n \"URI\",\n \"Version\",\n \"Chain ID\",\n \"Nonce\",\n \"Issued At\",\n \"Expiration Time\",\n \"Not Before\",\n \"Request ID\",\n]);\n\nfunction looksLikeKeyValue(line: string): boolean {\n const idx = line.indexOf(\": \");\n if (idx === -1) return false;\n return KNOWN_KEYS.has(line.slice(0, idx));\n}\n\nfunction requireField(fields: Map<string, string>, key: string): string {\n const value = fields.get(key);\n if (value === undefined) {\n throw new Error(`parseLoginMessage: missing required field \"${key}\"`);\n }\n return value;\n}\n\nfunction optionalDate(\n fields: Map<string, string>,\n key: string,\n): Date | undefined {\n const raw = fields.get(key);\n if (raw === undefined) return undefined;\n return new Date(raw);\n}\n","import { keccak256, recoverTypedDataAddress } from \"viem\";\nimport type { Address, Hex, WalletClient } from \"viem\";\n\nexport const SPONSOR_AUTH_DOMAIN_NAME = \"PafiSponsorAuth\";\n\nexport const SPONSOR_AUTH_TYPES = {\n SponsorAuth: [\n { name: \"chainId\", type: \"uint256\" },\n { name: \"sender\", type: \"address\" },\n { name: \"callDataHash\", type: \"bytes32\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"expiresAt\", type: \"uint256\" },\n { name: \"scenario\", type: \"string\" },\n { name: \"issuerId\", type: \"string\" },\n ],\n} as const;\n\nexport interface SponsorAuthPayload {\n chainId: number;\n sender: Address;\n callDataHash: Hex;\n nonce: bigint;\n expiresAt: number;\n scenario: string;\n issuerId: string;\n}\n\nexport interface SponsorAuthVerifyResult {\n ok: boolean;\n recoveredAddress?: Address;\n reason?: \"EXPIRED\" | \"INVALID_SIGNER\" | \"INVALID_SIGNATURE_FORMAT\";\n}\n\nexport function buildSponsorAuthDomain(chainId: number) {\n return {\n name: SPONSOR_AUTH_DOMAIN_NAME,\n version: \"1\",\n chainId,\n verifyingContract: \"0x0000000000000000000000000000000000000000\" as Address,\n };\n}\n\nfunction buildMessage(payload: SponsorAuthPayload) {\n return {\n chainId: BigInt(payload.chainId),\n sender: payload.sender,\n callDataHash: payload.callDataHash,\n nonce: payload.nonce,\n expiresAt: BigInt(payload.expiresAt),\n scenario: payload.scenario,\n issuerId: payload.issuerId,\n };\n}\n\nexport function buildSponsorAuthTypedData(payload: SponsorAuthPayload) {\n return {\n domain: buildSponsorAuthDomain(payload.chainId),\n types: SPONSOR_AUTH_TYPES,\n primaryType: \"SponsorAuth\" as const,\n message: buildMessage(payload),\n };\n}\n\nexport function computeCallDataHash(callData: Hex): Hex {\n return keccak256(callData);\n}\n\nexport async function signSponsorAuth(\n wallet: WalletClient,\n payload: SponsorAuthPayload,\n): Promise<Hex> {\n const { domain, types, primaryType, message } =\n buildSponsorAuthTypedData(payload);\n return wallet.signTypedData({\n account: wallet.account!,\n domain,\n types,\n primaryType,\n message,\n });\n}\n\nexport async function verifySponsorAuth(\n payload: SponsorAuthPayload,\n signature: Hex,\n expectedSigner: Address,\n): Promise<SponsorAuthVerifyResult> {\n const nowSec = Math.floor(Date.now() / 1000);\n if (payload.expiresAt < nowSec) {\n return { ok: false, reason: \"EXPIRED\" };\n }\n\n if (signature.length < 132) {\n return { ok: false, reason: \"INVALID_SIGNATURE_FORMAT\" };\n }\n\n let recovered: Address;\n try {\n const { domain, types, primaryType, message } =\n buildSponsorAuthTypedData(payload);\n recovered = await recoverTypedDataAddress({\n domain,\n types,\n primaryType,\n message,\n signature,\n });\n } catch {\n return { ok: false, reason: \"INVALID_SIGNATURE_FORMAT\" };\n }\n\n if (recovered.toLowerCase() !== expectedSigner.toLowerCase()) {\n return { ok: false, reason: \"INVALID_SIGNER\", recoveredAddress: recovered };\n }\n\n return { ok: true, recoveredAddress: recovered };\n}\n"]}
|
|
@@ -261,6 +261,7 @@ function rawCallOp(target, data, value = 0n) {
|
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
// src/swap/buildSwapWithGasDeduction.ts
|
|
264
|
+
var PERMIT2_ADDRESS = _viem.getAddress.call(void 0, "0x000000000022d473030f116ddee9f6b43ac78ba3");
|
|
264
265
|
function buildSwapWithGasDeduction(params) {
|
|
265
266
|
if (params.amountIn <= 0n) {
|
|
266
267
|
throw new Error("buildSwapWithGasDeduction: amountIn must be positive");
|
|
@@ -292,12 +293,19 @@ function buildSwapWithGasDeduction(params) {
|
|
|
292
293
|
functionName: "execute",
|
|
293
294
|
args: [commands, inputs, params.deadline]
|
|
294
295
|
});
|
|
296
|
+
const permit2ApproveData = buildPermit2ApprovalCalldata(
|
|
297
|
+
params.pointTokenAddress,
|
|
298
|
+
params.universalRouterAddress,
|
|
299
|
+
params.amountIn,
|
|
300
|
+
Number(params.deadline)
|
|
301
|
+
);
|
|
295
302
|
const operations = [
|
|
296
303
|
erc20ApproveOp(
|
|
297
304
|
params.pointTokenAddress,
|
|
298
|
-
|
|
305
|
+
PERMIT2_ADDRESS,
|
|
299
306
|
params.amountIn
|
|
300
307
|
),
|
|
308
|
+
rawCallOp(PERMIT2_ADDRESS, permit2ApproveData),
|
|
301
309
|
rawCallOp(params.universalRouterAddress, swapCallData)
|
|
302
310
|
];
|
|
303
311
|
if (params.gasFeePt > 0n) {
|
|
@@ -348,4 +356,4 @@ function buildSwapWithGasDeduction(params) {
|
|
|
348
356
|
|
|
349
357
|
|
|
350
358
|
exports.PafiSDKError = PafiSDKError; exports.ConfigurationError = ConfigurationError; exports.SigningError = SigningError; exports.SimulationError = SimulationError; exports.ApiError = ApiError; exports.checkAllowance = checkAllowance; exports.buildErc20ApprovalCalldata = buildErc20ApprovalCalldata; exports.buildPermit2ApprovalCalldata = buildPermit2ApprovalCalldata; exports.V4_SWAP = V4_SWAP; exports.SWAP_EXACT_IN = SWAP_EXACT_IN; exports.SETTLE_ALL = SETTLE_ALL; exports.TAKE_ALL = TAKE_ALL; exports.buildV4SwapInput = buildV4SwapInput; exports.buildUniversalRouterExecuteArgs = buildUniversalRouterExecuteArgs; exports.buildSwapFromQuote = buildSwapFromQuote; exports.simulateSwap = simulateSwap; exports.BATCH_EXECUTOR_ABI = BATCH_EXECUTOR_ABI; exports.encodeBatchExecute = encodeBatchExecute; exports.buildPartialUserOperation = buildPartialUserOperation; exports.assembleUserOperation = assembleUserOperation; exports.erc20TransferOp = erc20TransferOp; exports.erc20ApproveOp = erc20ApproveOp; exports.erc20BurnOp = erc20BurnOp; exports.rawCallOp = rawCallOp; exports.buildSwapWithGasDeduction = buildSwapWithGasDeduction;
|
|
351
|
-
//# sourceMappingURL=chunk-
|
|
359
|
+
//# sourceMappingURL=chunk-TYIEMGMY.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/phitran/Pacific-Finance/pafi-backend/pafi-sdk/packages/core/dist/chunk-TYIEMGMY.cjs","../src/swap/approval.ts","../src/swap/universalRouter.ts","../src/errors.ts","../src/swap/simulate.ts","../src/swap/buildSwapWithGasDeduction.ts","../src/userop/batchExecute.ts","../src/userop/buildUserOperation.ts","../src/userop/operations.ts"],"names":["erc20Abi"],"mappings":"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EAAA;AACF;AAWa;AACJ,EAAA;AACG,IAAA;AACD,IAAA;AACkB,IAAA;AAClBA,MAAAA;AACS,MAAA;AACQ,MAAA;AACvB,IAAA;AACH,EAAA;AACF;AAWuE;AAC9D,EAAA;AACG,IAAA;AACD,IAAA;AACkB,IAAA;AAClB,MAAA;AACS,MAAA;AACD,MAAA;AACd,IAAA;AACH,EAAA;AACF;AAWa;AACkB,EAAA;AAC/B;ARgLwD;AACA;AKpPrB;AAyFX;AACK,EAAA;AACT,IAAA;AAClB,EAAA;AAC8B,EAAA;AAClB,IAAA;AACR,MAAA;AACF,IAAA;AACF,EAAA;AAC0B,EAAA;AACd,IAAA;AACR,MAAA;AACF,IAAA;AACF,EAAA;AACkC,EAAA;AACtB,IAAA;AACR,MAAA;AACF,IAAA;AACF,EAAA;AAE6B,EAAA;AACpB,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACT,EAAA;AAE6C,EAAA;AACtC,IAAA;AACS,IAAA;AAC0B,IAAA;AACzC,EAAA;AAE+B,EAAA;AACvB,IAAA;AACA,IAAA;AACA,IAAA;AACe,IAAA;AACxB,EAAA;AAEgC,EAAA;AAC9B,IAAA;AACS,MAAA;AACP,MAAA;AACO,MAAA;AACT,IAAA;AAC6C,IAAA;AACJ,IAAA;AAC3C,EAAA;AAE0B,EAAA;AACb,IAAA;AACT,MAAA;AACS,QAAA;AACA,QAAA;AACA,QAAA;AACT,MAAA;AACF,IAAA;AACF,EAAA;AAEiC,EAAA;AAChB,IAAA;AACD,IAAA;AACd,IAAA;AACW,IAAA;AACuC,MAAA;AAE5B,MAAA;AACkB,MAAA;AACxC,IAAA;AACD,EAAA;AACH;ALuJwD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/Users/phitran/Pacific-Finance/pafi-backend/pafi-sdk/packages/core/dist/chunk-TYIEMGMY.cjs","sourcesContent":[null,"import { encodeFunctionData } from \"viem\";\nimport type { Address, Hex, PublicClient } from \"viem\";\nimport { erc20Abi } from \"../abi/erc20\";\nimport { permit2Abi } from \"../abi/permit2\";\n\nexport async function checkAllowance(\n client: PublicClient,\n token: Address,\n owner: Address,\n spender: Address,\n): Promise<bigint> {\n return client.readContract({\n address: token,\n abi: erc20Abi,\n functionName: \"allowance\",\n args: [owner, spender],\n });\n}\n\n/**\n * Encode an ERC-20 approve(spender, amount) call.\n */\nexport function buildErc20ApprovalCalldata(\n spender: Address,\n amount: bigint,\n): Hex {\n return encodeFunctionData({\n abi: erc20Abi,\n functionName: \"approve\",\n args: [spender, amount],\n });\n}\n\n/**\n * Encode a Permit2 approve(token, spender, amount, expiration) call.\n */\nexport function buildPermit2ApprovalCalldata(\n token: Address,\n spender: Address,\n amount: bigint,\n expiration: number,\n): Hex {\n return encodeFunctionData({\n abi: permit2Abi,\n functionName: \"approve\",\n args: [token, spender, amount, expiration],\n });\n}\n","import { encodeAbiParameters, encodePacked } from \"viem\";\nimport type { Address, Hex } from \"viem\";\nimport type { PathKey, QuoteResult } from \"../types\";\n\n// -------------------------------------------------------------------------\n// V4 UniversalRouter command / action constants\n// Reference: https://github.com/Uniswap/v4-periphery/blob/main/src/libraries/Actions.sol\n// -------------------------------------------------------------------------\n\n/** UniversalRouter command byte for V4 swap */\nexport const V4_SWAP = 0x10 as const;\n\n/** V4 actions */\nexport const SWAP_EXACT_IN_SINGLE = 0x06 as const;\nexport const SWAP_EXACT_IN = 0x07 as const;\nexport const SETTLE_ALL = 0x0c as const;\nexport const TAKE_ALL = 0x0f as const;\n\n// -------------------------------------------------------------------------\n// ABI type strings matching Uniswap's V4Planner encoding\n// Reference: https://github.com/Uniswap/sdks/blob/main/sdks/v4-sdk/src/utils/v4Planner.ts\n//\n// IMPORTANT: PathKey.fee is uint256 in the V4 Router ABI (not uint24).\n// -------------------------------------------------------------------------\n\n// PathKey components for V4 Router ABI encoding.\n// IMPORTANT: fee is uint256 in the V4 Router (not uint24 as in PoolKey).\n// Reference: https://github.com/Uniswap/sdks/blob/main/sdks/v4-sdk/src/utils/v4Planner.ts\nconst PATH_KEY_ABI_COMPONENTS = [\n { name: \"intermediateCurrency\", type: \"address\" },\n { name: \"fee\", type: \"uint256\" },\n { name: \"tickSpacing\", type: \"int24\" },\n { name: \"hooks\", type: \"address\" },\n { name: \"hookData\", type: \"bytes\" },\n] as const;\n\nconst EXACT_INPUT_PARAMS_ABI = [\n { name: \"currencyIn\", type: \"address\" },\n {\n name: \"path\",\n type: \"tuple[]\",\n components: PATH_KEY_ABI_COMPONENTS,\n },\n { name: \"amountIn\", type: \"uint128\" },\n { name: \"amountOutMinimum\", type: \"uint128\" },\n] as const;\n\n/**\n * Build the calldata inputs[0] (the V4_SWAP command payload) for\n * UniversalRouter.execute.\n *\n * Actions encoded: SWAP_EXACT_IN → SETTLE_ALL → TAKE_ALL\n *\n * Encoding matches the Uniswap V4 SDK's V4Planner — each action's params\n * are individually ABI-encoded, then wrapped together with the action bytes.\n */\nexport function buildV4SwapInput(\n currencyIn: Address,\n path: PathKey[],\n amountIn: bigint,\n minAmountOut: bigint,\n outputCurrency: Address,\n): Hex {\n const actions = encodePacked(\n [\"uint8\", \"uint8\", \"uint8\"],\n [SWAP_EXACT_IN, SETTLE_ALL, TAKE_ALL],\n );\n\n // Param 0: ExactInputParams — encoded as a single tuple so the CalldataDecoder\n // can locate it via a single offset pointer. fee is uint256 per V4 Router spec.\n const swapParam = encodeAbiParameters(\n [{ name: \"swap\", type: \"tuple\", components: EXACT_INPUT_PARAMS_ABI }],\n [\n {\n currencyIn,\n path: path.map((p) => ({\n intermediateCurrency: p.intermediateCurrency,\n fee: BigInt(p.fee),\n tickSpacing: p.tickSpacing,\n hooks: p.hooks,\n hookData: p.hookData,\n })),\n amountIn,\n amountOutMinimum: minAmountOut,\n },\n ],\n );\n\n // Param 1: SETTLE_ALL { currency, maxAmount }\n const settleParam = encodeAbiParameters(\n [\n { name: \"currency\", type: \"address\" },\n { name: \"maxAmount\", type: \"uint256\" },\n ],\n [currencyIn, amountIn],\n );\n\n // Param 2: TAKE_ALL { currency, minAmount }\n const takeParam = encodeAbiParameters(\n [\n { name: \"currency\", type: \"address\" },\n { name: \"minAmount\", type: \"uint256\" },\n ],\n [outputCurrency, minAmountOut],\n );\n\n return encodeAbiParameters(\n [\n { name: \"actions\", type: \"bytes\" },\n { name: \"params\", type: \"bytes[]\" },\n ],\n [actions, [swapParam, settleParam, takeParam]],\n );\n}\n\n/**\n * Build the full commands + inputs args for UniversalRouter.execute.\n */\nexport function buildUniversalRouterExecuteArgs(\n currencyIn: Address,\n path: PathKey[],\n amountIn: bigint,\n minAmountOut: bigint,\n outputCurrency: Address,\n): { commands: Hex; inputs: Hex[] } {\n const commands = encodePacked([\"uint8\"], [V4_SWAP]);\n const inputs: Hex[] = [\n buildV4SwapInput(currencyIn, path, amountIn, minAmountOut, outputCurrency),\n ];\n return { commands, inputs };\n}\n\n/**\n * Build UniversalRouter execute args from a quote result.\n *\n * Takes the output of `findBestQuote` / `quoteBestRoute` and produces\n * ready-to-use `{ commands, inputs }` for `UniversalRouter.execute`.\n *\n * @param quote - Quote result containing the path\n * @param currencyIn - Input token address\n * @param currencyOut - Output token address\n * @param amountIn - Exact input amount (same value passed to the quoter)\n * @param minAmountOut - Minimum acceptable output (caller applies slippage)\n *\n * @deprecated Since v1.4 — the Issuer App no longer handles swaps.\n * For the new PT→USDT batch call on PAFI Web (Scenario 4 with\n * EIP-7702 gas deduction), use `buildSwapWithGasDeduction()` (v1.5).\n * This helper is kept for legacy v0.2.x consumers; will be removed in v2.0.\n */\nexport function buildSwapFromQuote(params: {\n quote: QuoteResult;\n currencyIn: Address;\n currencyOut: Address;\n amountIn: bigint;\n minAmountOut: bigint;\n}): { commands: Hex; inputs: Hex[] } {\n return buildUniversalRouterExecuteArgs(\n params.currencyIn,\n params.quote.path,\n params.amountIn,\n params.minAmountOut,\n params.currencyOut,\n );\n}\n","export class PafiSDKError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PafiSDKError\";\n }\n}\n\nexport class ConfigurationError extends PafiSDKError {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigurationError\";\n }\n}\n\nexport class SigningError extends PafiSDKError {\n constructor(message: string) {\n super(message);\n this.name = \"SigningError\";\n }\n}\n\nexport class SimulationError extends PafiSDKError {\n constructor(\n public operation: string,\n public reason: string,\n ) {\n super(`Simulation failed for ${operation}: ${reason}`);\n this.name = \"SimulationError\";\n }\n}\n\nexport class ApiError extends PafiSDKError {\n constructor(\n message: string,\n public status?: number,\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n","import type { Address, Hex, PublicClient } from \"viem\";\nimport { universalRouterAbi } from \"../abi/universalRouter\";\nimport { SimulationError } from \"../errors\";\n\nexport interface SwapSimulationResult {\n success: boolean;\n gasEstimate: bigint;\n}\n\n/**\n * Simulate a UniversalRouter.execute swap call via eth_call (no gas spent).\n *\n * Runs the full V4 swap flow — token transfer via Permit2, swap via\n * PoolManager, output settlement — without submitting a transaction.\n * If the simulation reverts, throws a `SimulationError` with the reason.\n *\n * @param client - viem PublicClient\n * @param routerAddress - UniversalRouter contract address\n * @param commands - Packed command bytes (from buildSwapFromQuote)\n * @param inputs - Encoded inputs per command (from buildSwapFromQuote)\n * @param deadline - Unix timestamp after which the tx expires\n * @param from - Address that will execute the swap\n */\nexport async function simulateSwap(\n client: PublicClient,\n routerAddress: Address,\n commands: Hex,\n inputs: Hex[],\n deadline: bigint,\n from: Address,\n): Promise<SwapSimulationResult> {\n try {\n const gasEstimate = await client.estimateContractGas({\n address: routerAddress,\n abi: universalRouterAbi,\n functionName: \"execute\",\n args: [commands, inputs, deadline],\n account: from,\n });\n\n return { success: true, gasEstimate };\n } catch (error: unknown) {\n const message =\n error instanceof Error ? error.message : \"Unknown simulation error\";\n throw new SimulationError(\"swap\", message);\n }\n}\n","import { encodeFunctionData, getAddress } from \"viem\";\nimport type { Address, Hex } from \"viem\";\nimport { universalRouterAbi } from \"../abi/universalRouter\";\nimport type { PathKey } from \"../types\";\nimport { buildPartialUserOperation } from \"../userop/buildUserOperation\";\nimport type { PartialUserOperation } from \"../userop/types\";\nimport {\n erc20ApproveOp,\n erc20TransferOp,\n rawCallOp,\n} from \"../userop/operations\";\nimport type { Operation } from \"../userop/types\";\nimport { buildUniversalRouterExecuteArgs } from \"./universalRouter\";\nimport { buildPermit2ApprovalCalldata } from \"./approval\";\n\n// Permit2 address used by the PAFI UniversalRouter on Base mainnet.\n// NOTE: This is NOT the canonical Permit2 (0x...c2ccca1d). The PAFI router\n// embeds 0x000000000022d473030f116ddee9f6b43ac78ba3 — verified from bytecode.\nconst PERMIT2_ADDRESS = getAddress(\"0x000000000022d473030f116ddee9f6b43ac78ba3\");\n\n/**\n * v1.5 — Scenario 4: Swap PT → USDT on PAFI Web with gas fee\n * deducted in PT from the user's balance.\n *\n * Builds an unsigned `PartialUserOperation` that packages up to four\n * inner calls into a single `BatchExecutor.execute(calls[])`:\n *\n * 1. `PT.approve(Permit2, amountIn)` — grant Permit2 ERC-20 allowance\n * 2. `Permit2.approve(PT, router, amountIn, deadline)` — authorize\n * the UniversalRouter to pull PT via Permit2\n * 3. `UniversalRouter.execute(commands, inputs, deadline)` — V4 swap\n * PT → USDT; user receives ≥ `minAmountOut` USDT\n * 4. `PT.transfer(feeRecipient, gasFeePt)` — pay the operator back\n * for sponsoring the gas, in PT (omitted when `gasFeePt` is 0)\n *\n * The user's wallet must hold `amountIn + gasFeePt` PT before the\n * UserOp runs. All inner calls execute atomically via EIP-7702\n * delegation (`msg.sender = user`), so a reverting swap unwinds\n * the approvals and fee transfer too.\n *\n * ## Fee model\n *\n * The gas fee is a separate `transfer` after the swap — it does NOT\n * come out of the USDT output, because that output goes straight to\n * the user's wallet with no intermediate hook.\n *\n * If the FE wants \"user receives exactly X USDT after gas\":\n * 1. Quote PT→USDT for candidate `amountIn` values\n * 2. Pick an `amountIn` where `minAmountOut ≈ X`\n * 3. Separately compute `gasFeePt` from the operator's rate\n * 4. Ensure user's PT balance ≥ `amountIn + gasFeePt`\n *\n * ## Order of operations\n *\n * Fee transfer is last so a reverting swap also refunds the fee\n * (atomic batch revert semantics).\n */\nexport interface BuildSwapWithGasDeductionParams {\n /** User's EOA (with EIP-7702 delegation to BatchExecutor). */\n userAddress: Address;\n /** ERC-4337 account nonce — fetched from EntryPoint by the caller. */\n aaNonce: bigint;\n\n /** PT token address being swapped. */\n pointTokenAddress: Address;\n /** Destination currency (typically USDT). */\n outputTokenAddress: Address;\n /** UniversalRouter contract address (chain-specific). */\n universalRouterAddress: Address;\n\n /** PT units to swap. User's balance must be ≥ `amountIn + gasFeePt`. */\n amountIn: bigint;\n /**\n * Minimum USDT to accept out of the swap. Caller applies slippage\n * (typically ~0.5-1%) against a fresh quote. Sub-minimum swap reverts.\n */\n minAmountOut: bigint;\n\n /** V4 pool path for the swap. Single-hop = 1 PathKey. */\n swapPath: PathKey[];\n /** Unix seconds. After this, the router rejects the swap. */\n deadline: bigint;\n\n /** PT amount transferred to `feeRecipient` as gas fee recovery. */\n gasFeePt: bigint;\n /** Where the gas fee lands — typically the operator or fee collector. */\n feeRecipient: Address;\n\n /** Override ERC-4337 gas estimates. Defaults are conservative; tune down for cheaper UserOps. */\n gasLimits?: {\n callGasLimit?: bigint;\n verificationGasLimit?: bigint;\n preVerificationGas?: bigint;\n };\n}\n\n/**\n * Build an unsigned UserOp for Scenario 4. Returns a\n * `PartialUserOperation` — caller attaches paymaster sponsorship (via\n * `POST /api/paymaster/sponsor`), adds the user's UserOp-hash\n * signature, and submits to the Bundler.\n *\n * @throws when `amountIn` or `gasFeePt` is not positive, or when\n * `swapPath` is empty (at least one PathKey required).\n */\nexport function buildSwapWithGasDeduction(\n params: BuildSwapWithGasDeductionParams,\n): PartialUserOperation {\n if (params.amountIn <= 0n) {\n throw new Error(\"buildSwapWithGasDeduction: amountIn must be positive\");\n }\n if (params.minAmountOut < 0n) {\n throw new Error(\n \"buildSwapWithGasDeduction: minAmountOut must be non-negative\",\n );\n }\n if (params.gasFeePt < 0n) {\n throw new Error(\n \"buildSwapWithGasDeduction: gasFeePt must be non-negative\",\n );\n }\n if (params.swapPath.length === 0) {\n throw new Error(\n \"buildSwapWithGasDeduction: swapPath must contain at least one PathKey\",\n );\n }\n\n const { commands, inputs } = buildUniversalRouterExecuteArgs(\n params.pointTokenAddress,\n params.swapPath,\n params.amountIn,\n params.minAmountOut,\n params.outputTokenAddress,\n );\n\n const swapCallData: Hex = encodeFunctionData({\n abi: universalRouterAbi,\n functionName: \"execute\",\n args: [commands, inputs, params.deadline],\n });\n\n const permit2ApproveData: Hex = buildPermit2ApprovalCalldata(\n params.pointTokenAddress,\n params.universalRouterAddress,\n params.amountIn,\n Number(params.deadline),\n );\n\n const operations: Operation[] = [\n erc20ApproveOp(\n params.pointTokenAddress,\n PERMIT2_ADDRESS,\n params.amountIn,\n ),\n rawCallOp(PERMIT2_ADDRESS, permit2ApproveData),\n rawCallOp(params.universalRouterAddress, swapCallData),\n ];\n\n if (params.gasFeePt > 0n) {\n operations.push(\n erc20TransferOp(\n params.pointTokenAddress,\n params.feeRecipient,\n params.gasFeePt,\n ),\n );\n }\n\n return buildPartialUserOperation({\n sender: params.userAddress,\n nonce: params.aaNonce,\n operations,\n gasLimits: {\n callGasLimit: params.gasLimits?.callGasLimit ?? 700_000n,\n verificationGasLimit:\n params.gasLimits?.verificationGasLimit ?? 150_000n,\n preVerificationGas: params.gasLimits?.preVerificationGas ?? 50_000n,\n },\n });\n}\n","import { encodeFunctionData, parseAbi } from \"viem\";\nimport type { Hex } from \"viem\";\nimport type { Operation } from \"./types\";\n\n/**\n * Standard BatchExecutor ABI — a contract that takes an array of calls\n * and invokes each one in sequence, reverting all if any fail.\n *\n * Compatible with OpenZeppelin `Account.execute(Call[])`, Biconomy\n * `executeBatch`, Safe `MultiSend`, and most EIP-7702 delegation\n * targets. The exact deployed address is supplied by the infra team\n * (see [V1.4_V1.5_READINESS.md B2]).\n */\nexport const BATCH_EXECUTOR_ABI = parseAbi([\n \"function execute((address target, uint256 value, bytes data)[] calls)\",\n]);\n\n/**\n * Encode a batch of operations into calldata for `BatchExecutor.execute()`.\n * The resulting calldata goes into `UserOperation.callData`.\n *\n * When the EOA has an EIP-7702 delegation to a BatchExecutor, calling\n * this calldata against the EOA runs all operations with\n * `msg.sender = EOA` for each inner call.\n *\n * @param operations batch of calls, in execution order\n * @returns calldata bytes for `execute((address,uint256,bytes)[])`\n */\nexport function encodeBatchExecute(operations: Operation[]): Hex {\n if (operations.length === 0) {\n throw new Error(\"encodeBatchExecute: operations array must not be empty\");\n }\n return encodeFunctionData({\n abi: BATCH_EXECUTOR_ABI,\n functionName: \"execute\",\n args: [\n operations.map((op) => ({\n target: op.target,\n value: op.value,\n data: op.data,\n })),\n ],\n });\n}\n","import type { Address } from \"viem\";\nimport type { Operation, PartialUserOperation, UserOperation } from \"./types\";\nimport { encodeBatchExecute } from \"./batchExecute\";\n\n/**\n * Default gas limits — rough upper bounds for a 2-op batch on Base.\n * Bundler re-estimates before submission, so these are only used when\n * the caller doesn't supply their own.\n */\nconst DEFAULT_CALL_GAS_LIMIT = 500_000n;\nconst DEFAULT_VERIFICATION_GAS_LIMIT = 150_000n;\nconst DEFAULT_PRE_VERIFICATION_GAS = 50_000n;\n\nexport interface BuildPartialUserOpParams {\n /** User's EOA (with EIP-7702 delegation). */\n sender: Address;\n /** Batch of operations — encoded into callData via `encodeBatchExecute`. */\n operations: Operation[];\n /** EntryPoint nonce for this sender. Caller fetches from the EntryPoint contract. */\n nonce: bigint;\n /** Optional gas overrides; bundler re-estimates before submission. */\n gasLimits?: {\n callGasLimit?: bigint;\n verificationGasLimit?: bigint;\n preVerificationGas?: bigint;\n };\n /** Optional fee overrides; bundler usually fills these. */\n feeOverrides?: {\n maxFeePerGas?: bigint;\n maxPriorityFeePerGas?: bigint;\n };\n}\n\n/**\n * Build a partial ERC-4337 UserOperation from a batch of operations.\n * Paymaster fields and signature are populated later:\n * 1. Call `PafiBackendClient.requestSponsorship()` → get paymaster fields\n * 2. Compute userOpHash and have the user sign it (via Privy)\n * 3. Attach `signature` → submit to bundler\n *\n * This function is a pure struct builder — no network calls.\n */\nexport function buildPartialUserOperation(\n params: BuildPartialUserOpParams,\n): PartialUserOperation {\n return {\n sender: params.sender,\n nonce: params.nonce,\n callData: encodeBatchExecute(params.operations),\n callGasLimit: params.gasLimits?.callGasLimit ?? DEFAULT_CALL_GAS_LIMIT,\n verificationGasLimit:\n params.gasLimits?.verificationGasLimit ??\n DEFAULT_VERIFICATION_GAS_LIMIT,\n preVerificationGas:\n params.gasLimits?.preVerificationGas ?? DEFAULT_PRE_VERIFICATION_GAS,\n maxFeePerGas: params.feeOverrides?.maxFeePerGas ?? 0n,\n maxPriorityFeePerGas: params.feeOverrides?.maxPriorityFeePerGas ?? 0n,\n };\n}\n\n/**\n * Assemble a full UserOperation once paymaster fields + signature are\n * known. Used after `PafiBackendClient.requestSponsorship()` and user\n * signing complete.\n */\nexport function assembleUserOperation(\n partial: PartialUserOperation,\n paymaster: {\n paymaster: Address;\n paymasterData: `0x${string}`;\n paymasterVerificationGasLimit: bigint;\n paymasterPostOpGasLimit: bigint;\n },\n signature: `0x${string}`,\n): UserOperation {\n return {\n ...partial,\n paymaster: paymaster.paymaster,\n paymasterData: paymaster.paymasterData,\n paymasterVerificationGasLimit: paymaster.paymasterVerificationGasLimit,\n paymasterPostOpGasLimit: paymaster.paymasterPostOpGasLimit,\n signature,\n };\n}\n","import { encodeFunctionData, erc20Abi, parseAbi } from \"viem\";\nimport type { Address } from \"viem\";\nimport type { Operation } from \"./types\";\n\n/**\n * ERC20Burnable extension — `burn(uint256 amount)` burns from msg.sender.\n * The EOA (via EIP-7702 delegation) is the `msg.sender` when a batch\n * runs — so this burns the user's balance without any role check.\n */\nconst ERC20_BURNABLE_ABI = parseAbi([\"function burn(uint256 amount)\"]);\n\n/**\n * Build an ERC-20 `transfer(to, amount)` operation. Used inside a batch\n * to move fee tokens from the user to the fee recipient atomically with\n * the main action.\n */\nexport function erc20TransferOp(\n token: Address,\n to: Address,\n amount: bigint,\n): Operation {\n return {\n target: token,\n value: 0n,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"transfer\",\n args: [to, amount],\n }),\n };\n}\n\n/**\n * Build an ERC-20 `approve(spender, amount)` operation. Used inside a\n * batch before a swap / deposit call so the AMM / protocol can pull\n * tokens from the user.\n */\nexport function erc20ApproveOp(\n token: Address,\n spender: Address,\n amount: bigint,\n): Operation {\n return {\n target: token,\n value: 0n,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"approve\",\n args: [spender, amount],\n }),\n };\n}\n\n/**\n * Build an ERC-20 `burn(amount)` operation (OpenZeppelin ERC20Burnable\n * extension). Burns from `msg.sender`, which — via EIP-7702 — is the\n * user's EOA.\n *\n * Requires the PointToken contract to expose a public `burn(uint256)`\n * without a role check. See\n * [SDK_V1.4_TASKS.md §11 — PointToken.burn callable via batch].\n */\nexport function erc20BurnOp(token: Address, amount: bigint): Operation {\n return {\n target: token,\n value: 0n,\n data: encodeFunctionData({\n abi: ERC20_BURNABLE_ABI,\n functionName: \"burn\",\n args: [amount],\n }),\n };\n}\n\n/**\n * Build a raw call operation with caller-supplied calldata. Useful for\n * non-ERC-20 contracts (PoolManager.swap, PerpDEX.deposit, Relayer.mint)\n * where the encoding is specific to that protocol.\n */\nexport function rawCallOp(\n target: Address,\n data: `0x${string}`,\n value: bigint = 0n,\n): Operation {\n return { target, value, data };\n}\n"]}
|