@pafi-dev/core 0.9.6 → 0.10.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 +194 -189
- package/dist/{chunk-5NEAI2BH.cjs → chunk-4NTU7XGP.cjs} +2 -54
- package/dist/chunk-4NTU7XGP.cjs.map +1 -0
- package/dist/{chunk-BNO5SM25.cjs → chunk-BBQLGBOD.cjs} +2 -11
- package/dist/{chunk-Y5EYH2SQ.js.map → chunk-BBQLGBOD.cjs.map} +1 -1
- package/dist/{chunk-Y5EYH2SQ.js → chunk-J7EYOLMI.js} +1 -10
- package/dist/chunk-J7EYOLMI.js.map +1 -0
- package/dist/{chunk-HJYHGCMT.js → chunk-RVSW7I6U.js} +2 -54
- package/dist/chunk-RVSW7I6U.js.map +1 -0
- package/dist/contract/index.cjs +2 -4
- package/dist/contract/index.cjs.map +1 -1
- package/dist/contract/index.d.cts +2 -11
- package/dist/contract/index.d.ts +2 -11
- package/dist/contract/index.js +1 -3
- package/dist/eip712/index.cjs +2 -8
- package/dist/eip712/index.cjs.map +1 -1
- package/dist/eip712/index.d.cts +2 -41
- package/dist/eip712/index.d.ts +2 -41
- package/dist/eip712/index.js +3 -9
- package/dist/index.cjs +13 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -84
- package/dist/index.d.ts +36 -84
- package/dist/index.js +11 -47
- package/dist/index.js.map +1 -1
- package/dist/{types-DWLZNgcw.d.cts → types-B3UivyQ1.d.cts} +1 -10
- package/dist/{types-DWLZNgcw.d.ts → types-B3UivyQ1.d.ts} +1 -10
- package/package.json +10 -1
- package/dist/chunk-5NEAI2BH.cjs.map +0 -1
- package/dist/chunk-BNO5SM25.cjs.map +0 -1
- package/dist/chunk-HJYHGCMT.js.map +0 -1
package/README.md
CHANGED
|
@@ -4,21 +4,43 @@
|
|
|
4
4
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
5
5
|
|
|
6
6
|
Pure primitives for the PAFI point-token system. EIP-712 signing,
|
|
7
|
-
contract ABIs + addresses, ERC-4337 UserOp building, EIP-7702
|
|
8
|
-
delegation, sponsor-auth signing, perp deposit calldata, fee quoting
|
|
7
|
+
contract ABIs + addresses (v1.6), ERC-4337 UserOp building, EIP-7702
|
|
8
|
+
delegation, sponsor-auth signing, perp deposit calldata, fee quoting,
|
|
9
|
+
MintFeeWrapper helpers.
|
|
9
10
|
|
|
10
11
|
**Browser + Node-safe.** Zero HTTP client. Peer-dep: `viem ^2`.
|
|
11
12
|
|
|
12
13
|
---
|
|
13
14
|
|
|
14
|
-
##
|
|
15
|
+
## What's new in 0.10.0 (breaking)
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- `
|
|
17
|
+
| Change | Detail |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `ReceiverConsent` removed | The `ReceiverConsent` EIP-712 type, helpers (`buildReceiverConsentTypedData`, `signReceiverConsent`, `verifyReceiverConsent`), constants (`receiverConsentTypes`), and contract reader (`getReceiverConsentNonce`) are all **deleted**. The deployed `PointToken` contract never had a 3rd "sponsored" mint path — that pattern is implemented at the relayer layer (sponsor-relayer pays gas for path-2 `MintForRequest` sig-gated mint). The previous fallback that read ERC-2612 `nonces(owner)` was semantically wrong and is gone. |
|
|
20
|
+
| `PafiSDK.consent` namespace removed | The convenience class no longer exposes `consent.buildTypedData / sign / verify / getNonce`. |
|
|
21
|
+
| Action required for callers | Replace any `signReceiverConsent` / `getReceiverConsentNonce` usage with the path-2 sig-gated mint flow (`MintRequest` + `getMintRequestNonce`). |
|
|
22
|
+
|
|
23
|
+
### What's new in v1.6 (since 0.9.0)
|
|
24
|
+
|
|
25
|
+
| Change | Detail |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `MintFeeWrapper` (NEW) | Single global wrapper contract that skims a configurable fee on every sig-gated mint and distributes to per-PT recipients |
|
|
28
|
+
| EIP-712 typehash | `MintRequest(to, amount, nonce, deadline)` → **`MintForRequest(user, receiver, amount, nonce, deadline)`** (5 fields) |
|
|
29
|
+
| Issuer struct | Dropped `declaredTotalSupply` + `capBasisPoints` — caps moved to `MintingOracle.tokenCaps(pointToken)` (per-token, not per-issuer) |
|
|
30
|
+
| `verifyMintCap` signature | Now takes `pointToken` as first arg |
|
|
31
|
+
| New helpers | `getMintFeeBps`, `getMintFeeRecipients`, `getTokenCap` |
|
|
32
|
+
| Subgraph URL | Hardcoded to `pafi-subgraph-v3` (`getPafiServiceUrls(chainId)`) |
|
|
33
|
+
| `pafiHook` | DEPRECATED — V4 swap-time fee removed entirely in v1.6 |
|
|
34
|
+
| `getPtPerUsdt18dec` math fix (0.9.6) | Subgraph V4 returns HUMAN-readable price; old formula `10^24/raw` was off by ~10^11 |
|
|
19
35
|
|
|
20
36
|
---
|
|
21
37
|
|
|
38
|
+
## Requirements
|
|
39
|
+
|
|
40
|
+
- Node.js ≥ 18 (or modern browser with native `fetch`)
|
|
41
|
+
- TypeScript ≥ 5.0
|
|
42
|
+
- `viem` ^2.0.0 (peer)
|
|
43
|
+
|
|
22
44
|
## Installation
|
|
23
45
|
|
|
24
46
|
```bash
|
|
@@ -27,10 +49,9 @@ pnpm add @pafi-dev/core viem
|
|
|
27
49
|
|
|
28
50
|
---
|
|
29
51
|
|
|
30
|
-
##
|
|
52
|
+
## Package layout (v1.6)
|
|
31
53
|
|
|
32
|
-
Core ships **data + primitives** only. Higher-level orchestration
|
|
33
|
-
in sibling packages:
|
|
54
|
+
Core ships **data + primitives** only. Higher-level orchestration in siblings:
|
|
34
55
|
|
|
35
56
|
| Concern | Package |
|
|
36
57
|
| --- | --- |
|
|
@@ -39,75 +60,62 @@ in sibling packages:
|
|
|
39
60
|
| Issuer DB ledger (TypeORM + Postgres) | `@pafi-dev/issuer-postgres` |
|
|
40
61
|
| Trading (swap + quote, FE-callable) | `@pafi-dev/trading` |
|
|
41
62
|
|
|
42
|
-
> **0.6.0 (2026-04-27):** swap UserOp builders + V4 quoting moved
|
|
43
|
-
> from core to `@pafi-dev/trading`. Core retains the underlying
|
|
44
|
-
> `universalRouterAbi`, `permit2Abi`, `v4QuoterAbi`, `PoolKey`,
|
|
45
|
-
> `PathKey`, `QuoteResult` types — trading wraps them with the actual
|
|
46
|
-
> swap logic. The `PafiSDK` class also drops `quote` / `swap`
|
|
47
|
-
> namespaces; use trading or import primitives directly.
|
|
48
|
-
>
|
|
49
|
-
> **0.6.1 (2026-04-27):** added `quoteOperatorFeeUsdt` so FE can
|
|
50
|
-
> compute USDT-denominated gas fee without round-tripping the issuer
|
|
51
|
-
> backend (`/gas-fee` is now optional).
|
|
52
|
-
>
|
|
53
|
-
> **0.7.5 (2026-04-28):** added `delegateDirect()` — FE one-shot EIP-7702
|
|
54
|
-
> delegation that user pays gas for. Bypasses the AA + sponsor-relayer
|
|
55
|
-
> stack entirely. See [section below](#delegatedirect--fe-one-shot-delegation-no-aa--no-sponsor).
|
|
56
|
-
|
|
57
63
|
---
|
|
58
64
|
|
|
59
|
-
##
|
|
65
|
+
## Exports cheatsheet
|
|
60
66
|
|
|
61
|
-
| Symbol / area |
|
|
67
|
+
| Symbol / area | Provides |
|
|
62
68
|
| --- | --- |
|
|
63
|
-
| `getContractAddresses(chainId)` | All deployed PAFI
|
|
64
|
-
| `signMintRequest`, `verifyMintRequest` | EIP-712 sign
|
|
65
|
-
| `signBurnRequest`, `verifyBurnRequest` | EIP-712
|
|
66
|
-
| `signReceiverConsent`, `verifyReceiverConsent` | EIP-712 for sponsored-mint consent |
|
|
69
|
+
| `getContractAddresses(chainId)` | All deployed PAFI v1.6 addresses keyed by chain |
|
|
70
|
+
| `signMintRequest`, `verifyMintRequest`, `buildMintRequestTypedData` | EIP-712 sign/recover for v1.6 `MintForRequest` (5 fields) |
|
|
71
|
+
| `signBurnRequest`, `verifyBurnRequest`, `buildBurnRequestTypedData` | EIP-712 for `BurnRequest` |
|
|
67
72
|
| `signSponsorAuth`, `verifySponsorAuth`, `buildAndSignSponsorAuth` | EIP-712 for sponsor-relayer auth |
|
|
68
73
|
| `buildPartialUserOperation`, `assembleUserOperation`, `computeUserOpHash` | ERC-4337 v0.7+ UserOp builder + hash |
|
|
69
|
-
| `encodeBatchExecute`, `decodeBatchExecuteCalls` | BatchExecutor (
|
|
70
|
-
| `buildDelegationUserOp`, `computeAuthorizationHash`, `parseEip7702DelegatedAddress` | EIP-7702 helpers |
|
|
71
|
-
| `splitAuthorizationSig`, `buildEip7702Authorization` | Split user's authSig + assemble bundler tuple |
|
|
72
|
-
| `delegateDirect` | One-shot FE-direct EIP-7702 delegation (user pays gas, no AA) |
|
|
74
|
+
| `encodeBatchExecute`, `decodeBatchExecuteCalls` | BatchExecutor (Pimlico Simple7702Account) calldata |
|
|
75
|
+
| `buildDelegationUserOp`, `computeAuthorizationHash`, `parseEip7702DelegatedAddress`, `splitAuthorizationSig`, `buildEip7702Authorization`, `delegateDirect` | EIP-7702 helpers (build + introspect) |
|
|
73
76
|
| `buildPerpDepositViaRelay`, `buildPerpDepositWithGasDeduction`, `ORDERLY_RELAY_ABI`, `ORDERLY_VAULT_ABI`, `BROKER_HASHES`, `TOKEN_HASHES`, `computeAccountId` | Orderly perp deposit calldata + types |
|
|
74
|
-
| `quoteOperatorFeePt`, `quoteOperatorFeeUsdt` |
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
77
|
+
| `quoteOperatorFeePt`, `quoteOperatorFeeUsdt` | Gas-reimbursement fee quoter (Chainlink + V4 subgraph) |
|
|
78
|
+
| `getMintFeeBps`, `getMintFeeRecipients` | v1.6 — read wrapper fee config per pointToken |
|
|
79
|
+
| `getTokenCap` | v1.6 — read `MintingOracle.tokenCaps(pointToken)` |
|
|
80
|
+
| `verifyMintCap`, `getPointTokenIssuer` | MintingOracle read helpers (v1.6 signature) |
|
|
81
|
+
| `getIssuer`, `isActiveIssuer`, `issuerRegistryGetIssuerFlatAbi` | IssuerRegistry helpers (v1.6 — 7 fields) |
|
|
82
|
+
| `getMintRequestNonce`, `getBurnRequestNonce`, `getPointTokenBalance`, `isMinter`, `getTokenName`, `getPointTokenIssuerAddress` | PointToken read helpers |
|
|
83
|
+
| `fetchPafiPools`, `PAFI_SUBGRAPH_URL` | Pool discovery via PAFI subgraph v3 |
|
|
84
|
+
| `getPafiServiceUrls(chainId)` | Hardcoded PAFI service endpoints (sponsorRelayer, issuerApi) |
|
|
85
|
+
| `pointTokenAbi` (alias `POINT_TOKEN_V2_ABI`), `issuerRegistryAbi`, `mintingOracleAbi`, `mintFeeWrapperAbi`, `pointTokenFactoryAbi`, `erc20Abi`, `permit2Abi`, `universalRouterAbi`, `v4QuoterAbi` | Contract ABIs (regenerated from Foundry artifacts) |
|
|
86
|
+
| `createLoginMessage` | EIP-4361 SIWE login builder |
|
|
80
87
|
|
|
81
88
|
---
|
|
82
89
|
|
|
83
|
-
## Contract addresses
|
|
90
|
+
## Contract addresses (v1.6)
|
|
84
91
|
|
|
85
92
|
```ts
|
|
86
93
|
import { getContractAddresses } from "@pafi-dev/core";
|
|
87
94
|
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
universalRouter,
|
|
99
|
-
} = getContractAddresses(8453);
|
|
95
|
+
const addr = getContractAddresses(8453); // Base mainnet
|
|
96
|
+
// addr.issuerRegistry = 0xAB1d1e117c41636f30bb10194Fe6B774B6Da9E01
|
|
97
|
+
// addr.mintingOracle = 0x2f4cf8C5F8b41efC970c5b46a5d905CeA1f871a0
|
|
98
|
+
// addr.mintFeeWrapper = 0xD324EE2e3220B23d1b1BfbB85f5bC1EF2E917B93 (NEW)
|
|
99
|
+
// addr.usdt = 0x3F7e71B150e97316Bb9f363A32c19CcD36ac2382
|
|
100
|
+
// addr.batchExecutor = 0xe6Cae83BdE06E4c305530e199D7217f42808555B (Pimlico Simple7702)
|
|
101
|
+
// addr.pafiFeeRecipient = ... (PAFI ops wallet)
|
|
102
|
+
// addr.chainlinkEthUsd = 0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70
|
|
103
|
+
// addr.pafiHook = 0x...dead (DEPRECATED in v1.6)
|
|
104
|
+
// addr.pointToken = dead-zero (PER-ISSUER — read from env or factory)
|
|
100
105
|
```
|
|
101
106
|
|
|
102
|
-
|
|
103
|
-
|
|
107
|
+
> Per-issuer `pointToken` clones are NOT in the chain-level address bag.
|
|
108
|
+
> Read from your issuer env (e.g. `POINT_TOKEN_ADDRESS`) or
|
|
109
|
+
> `PointTokenFactory.createToken()` at runtime.
|
|
110
|
+
|
|
111
|
+
Deploy block: **45683465** (canonical for all v1.6 indexers).
|
|
104
112
|
|
|
105
113
|
---
|
|
106
114
|
|
|
107
|
-
## EIP-712
|
|
115
|
+
## EIP-712 — `MintForRequest` (v1.6)
|
|
108
116
|
|
|
109
117
|
```ts
|
|
110
|
-
import { signMintRequest,
|
|
118
|
+
import { signMintRequest, verifyMintRequest } from "@pafi-dev/core";
|
|
111
119
|
import { privateKeyToAccount } from "viem/accounts";
|
|
112
120
|
import { createWalletClient, http } from "viem";
|
|
113
121
|
|
|
@@ -116,183 +124,131 @@ const wallet = createWalletClient({
|
|
|
116
124
|
transport: http(),
|
|
117
125
|
});
|
|
118
126
|
|
|
119
|
-
const { pointToken } = getContractAddresses(8453);
|
|
120
127
|
const sig = await signMintRequest(
|
|
121
128
|
wallet,
|
|
122
|
-
{ name: "POINT", chainId: 8453, verifyingContract:
|
|
129
|
+
{ name: "POINT", chainId: 8453, verifyingContract: pointTokenAddress },
|
|
123
130
|
{
|
|
124
|
-
|
|
131
|
+
user, // off-chain spender (drives nonces)
|
|
132
|
+
receiver: wrapperAddress, // on-chain caller of PointToken.mint
|
|
133
|
+
// (= wrapper for wrapper-mediated; = user for direct)
|
|
125
134
|
amount: 1000n * 10n ** 18n,
|
|
126
|
-
nonce: currentMintRequestNonce,
|
|
135
|
+
nonce: currentMintRequestNonce, // from PointToken.mintRequestNonces(user)
|
|
127
136
|
deadline: BigInt(Math.floor(Date.now() / 1000) + 900),
|
|
128
137
|
},
|
|
129
138
|
);
|
|
130
139
|
|
|
131
|
-
// sig.serialized — bytes hex passed to PointToken.mint(...)
|
|
140
|
+
// sig.serialized — bytes hex passed to PointToken.mint(...) or wrapper.mintWithFee(...)
|
|
132
141
|
```
|
|
133
142
|
|
|
134
|
-
|
|
135
|
-
`
|
|
136
|
-
`viem WalletClient`.
|
|
143
|
+
Wrapper-mediated mint puts `receiver = wrapperAddress`; direct mint puts
|
|
144
|
+
`receiver = user`. The contract requires `msg.sender == receiver`.
|
|
137
145
|
|
|
138
146
|
---
|
|
139
147
|
|
|
140
|
-
##
|
|
148
|
+
## MintFeeWrapper helpers (v1.6)
|
|
141
149
|
|
|
142
150
|
```ts
|
|
143
|
-
import {
|
|
151
|
+
import { getMintFeeBps, getMintFeeRecipients, getContractAddresses } from "@pafi-dev/core";
|
|
144
152
|
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
{ target: pointToken, value: 0n, data: feeTransferCallData }, // optional
|
|
148
|
-
]);
|
|
153
|
+
const { mintFeeWrapper } = getContractAddresses(8453);
|
|
154
|
+
const POINT_TOKEN = "0x855c2046...";
|
|
149
155
|
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
});
|
|
156
|
+
const bps = await getMintFeeBps(provider, mintFeeWrapper, POINT_TOKEN);
|
|
157
|
+
// bps = 50 (= 0.50%)
|
|
158
|
+
|
|
159
|
+
const recipients = await getMintFeeRecipients(provider, mintFeeWrapper, POINT_TOKEN);
|
|
160
|
+
// [{ account: 0x..., basisPoints: 20 }, { account: 0x..., basisPoints: 30 }]
|
|
156
161
|
```
|
|
157
162
|
|
|
158
|
-
`
|
|
159
|
-
|
|
160
|
-
`personal_sign`.
|
|
163
|
+
Wrapper deducts `gross × bps / 10000` PT on every mint and distributes
|
|
164
|
+
to recipients. User receives `gross × (1 - bps/10000)` net.
|
|
161
165
|
|
|
162
166
|
---
|
|
163
167
|
|
|
164
|
-
##
|
|
168
|
+
## Operator fee quoter
|
|
165
169
|
|
|
166
|
-
|
|
167
|
-
import {
|
|
168
|
-
computeAuthorizationHash,
|
|
169
|
-
parseEip7702DelegatedAddress,
|
|
170
|
-
splitAuthorizationSig,
|
|
171
|
-
buildEip7702Authorization,
|
|
172
|
-
} from "@pafi-dev/core";
|
|
170
|
+
Two helpers for FE direct usage (no backend round-trip):
|
|
173
171
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const designator = parseEip7702DelegatedAddress(code); // null = not delegated
|
|
172
|
+
```ts
|
|
173
|
+
import { quoteOperatorFeeUsdt, quoteOperatorFeePt } from "@pafi-dev/core";
|
|
177
174
|
|
|
178
|
-
//
|
|
179
|
-
const
|
|
180
|
-
|
|
175
|
+
// USDT-denominated (replaces issuer's GET /gas-fee). Chainlink-only.
|
|
176
|
+
const gasFeeUsdt = await quoteOperatorFeeUsdt({
|
|
177
|
+
provider, chainId: 8453, scenario: "mint",
|
|
178
|
+
});
|
|
181
179
|
|
|
182
|
-
//
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
nonce: accountNonce,
|
|
188
|
-
authSig,
|
|
180
|
+
// PT-denominated (used by mint/burn flows). Adds V4 subgraph call.
|
|
181
|
+
const gasFeePt = await quoteOperatorFeePt({
|
|
182
|
+
provider, chainId: 8453, scenario: "mint",
|
|
183
|
+
pointTokenAddress: POINT_TOKEN,
|
|
184
|
+
allowStaleFallback: true, // recommended: don't block on subgraph outage
|
|
189
185
|
});
|
|
190
186
|
```
|
|
191
187
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
For the **FE-direct** path where the user pays gas in ETH and you don't
|
|
197
|
-
want a dependency on `permissionless` / Pimlico bundlers / PAFI
|
|
198
|
-
sponsor-relayer:
|
|
188
|
+
Both return `bigint` raw units. Fallback prices (`0.1 USDT/PT` default,
|
|
189
|
+
3000 USD/ETH default) used when oracles unreachable + `allowStaleFallback`
|
|
190
|
+
is true. Sponsor-relayer's `FeeValidator` runs the same math server-side
|
|
191
|
+
with a 5% tolerance window.
|
|
199
192
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
import { delegateDirect } from "@pafi-dev/core";
|
|
203
|
-
import { createWalletClient, custom, createPublicClient, http } from "viem";
|
|
204
|
-
import { base } from "viem/chains";
|
|
205
|
-
|
|
206
|
-
const publicClient = createPublicClient({ chain: base, transport: http() });
|
|
207
|
-
|
|
208
|
-
function DelegateButton() {
|
|
209
|
-
const { wallets } = useWallets();
|
|
210
|
-
const { signAuthorization } = useSign7702Authorization();
|
|
211
|
-
|
|
212
|
-
// Privy ALWAYS signs EIP-7702 with the embedded wallet — pick that
|
|
213
|
-
// one as the smart-account owner regardless of how user logged in.
|
|
214
|
-
const wallet = wallets.find((w) => w.walletClientType === "privy");
|
|
215
|
-
|
|
216
|
-
async function handleClick() {
|
|
217
|
-
if (!wallet) return;
|
|
218
|
-
const provider = await wallet.getEthereumProvider();
|
|
219
|
-
const walletClient = createWalletClient({
|
|
220
|
-
account: wallet.address as `0x${string}`,
|
|
221
|
-
chain: base,
|
|
222
|
-
transport: custom(provider),
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
const result = await delegateDirect({
|
|
226
|
-
userAddress: wallet.address as `0x${string}`,
|
|
227
|
-
chainId: 8453,
|
|
228
|
-
publicClient,
|
|
229
|
-
walletClient,
|
|
230
|
-
signAuthorization,
|
|
231
|
-
// optional: skipIfAlreadyDelegated (default true), waitForReceipt (default true)
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
if (result.status === "already-delegated") {
|
|
235
|
-
console.log("Already delegated to", result.delegatedTo);
|
|
236
|
-
} else {
|
|
237
|
-
console.log("Delegated! tx:", result.txHash);
|
|
238
|
-
// result.receipt — full TransactionReceipt when waitForReceipt=true
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
return <button onClick={handleClick}>Delegate</button>;
|
|
243
|
-
}
|
|
244
|
-
```
|
|
193
|
+
See [`docs/FEE_FLOW.md`](../../../docs/FEE_FLOW.md) in the main repo for
|
|
194
|
+
full math derivation.
|
|
245
195
|
|
|
246
|
-
|
|
196
|
+
---
|
|
247
197
|
|
|
248
|
-
|
|
249
|
-
2. `getTransactionCount(userAddress, 'pending')` → tx nonce.
|
|
250
|
-
3. `signAuthorization({ contractAddress, chainId, nonce })` — Privy hook signs with embedded wallet (raw `secp256k1_sign`, no EIP-191 prefix).
|
|
251
|
-
4. `walletClient.sendTransaction({ to: userAddress, data: '0x', authorizationList: [auth] })` — viem encodes a type-4 EIP-7702 transaction.
|
|
252
|
-
5. `waitForTransactionReceipt(txHash)` (optional).
|
|
198
|
+
## ERC-4337 UserOp building
|
|
253
199
|
|
|
254
|
-
|
|
200
|
+
```ts
|
|
201
|
+
import { encodeBatchExecute, buildPartialUserOperation } from "@pafi-dev/core";
|
|
255
202
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
203
|
+
const callData = encodeBatchExecute([
|
|
204
|
+
{ target: mintFeeWrapper, value: 0n, data: mintWithFeeCallData },
|
|
205
|
+
{ target: pointToken, value: 0n, data: feeTransferCallData },
|
|
206
|
+
]);
|
|
260
207
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
208
|
+
const partial = buildPartialUserOperation({
|
|
209
|
+
sender: userAddress,
|
|
210
|
+
nonce: aaNonce,
|
|
211
|
+
callData,
|
|
212
|
+
gasLimits: {
|
|
213
|
+
callGasLimit: 300_000n,
|
|
214
|
+
verificationGasLimit: 150_000n,
|
|
215
|
+
preVerificationGas: 50_000n,
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
```
|
|
265
219
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
infrastructure entirely.
|
|
220
|
+
`computeUserOpHash(userOp, chainId)` — EntryPoint v0.8 EIP-712 digest.
|
|
221
|
+
Mobile signs this hash via `eth_signTypedData_v4` (NOT `personal_sign` —
|
|
222
|
+
Pimlico Simple7702Account does raw `ecrecover` without EIP-191 prefix).
|
|
270
223
|
|
|
271
224
|
---
|
|
272
225
|
|
|
273
|
-
##
|
|
226
|
+
## EIP-7702 — `delegateDirect`
|
|
274
227
|
|
|
275
|
-
|
|
228
|
+
FE one-shot delegation, no AA / no sponsor:
|
|
276
229
|
|
|
277
230
|
```ts
|
|
278
|
-
import {
|
|
231
|
+
import { delegateDirect } from "@pafi-dev/core";
|
|
232
|
+
import { useSign7702Authorization, useWallets } from "@privy-io/react-auth";
|
|
279
233
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const gasFeeUsdt = await quoteOperatorFeeUsdt({ provider, chainId: 8453 });
|
|
234
|
+
const { signAuthorization } = useSign7702Authorization();
|
|
235
|
+
const wallet = useWallets().find((w) => w.walletClientType === "privy");
|
|
283
236
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const gasFeePt = await quoteOperatorFeePt({
|
|
287
|
-
provider,
|
|
237
|
+
const result = await delegateDirect({
|
|
238
|
+
userAddress: wallet.address,
|
|
288
239
|
chainId: 8453,
|
|
289
|
-
|
|
240
|
+
publicClient,
|
|
241
|
+
walletClient,
|
|
242
|
+
signAuthorization,
|
|
243
|
+
// optional: skipIfAlreadyDelegated (default true), waitForReceipt (default true)
|
|
290
244
|
});
|
|
245
|
+
|
|
246
|
+
// result.status: "already-delegated" | "broadcasted"
|
|
247
|
+
// result.txHash, result.delegatedTo, result.receipt?
|
|
291
248
|
```
|
|
292
249
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
between client and server is accepted.
|
|
250
|
+
**Privy embedded wallet only** — external wallets (MetaMask) can't sign
|
|
251
|
+
EIP-7702 (no raw `secp256k1_sign` exposed). User pays ~$0.01–0.10 ETH gas.
|
|
296
252
|
|
|
297
253
|
---
|
|
298
254
|
|
|
@@ -309,15 +265,64 @@ const sponsorAuth = await buildAndSignSponsorAuth({
|
|
|
309
265
|
issuerId: ISSUER_ID,
|
|
310
266
|
issuerSignerWallet, // KMS-backed in prod
|
|
311
267
|
});
|
|
268
|
+
// Pass to sponsor-relayer's POST /paymaster/sponsor as `sponsorAuth` field
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Issuer signer must be registered in `IssuerRegistry` (`signerAddress`
|
|
272
|
+
field) and whitelisted via `PointToken.addMinter(signer)`.
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Verify on-chain state (debug)
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
import {
|
|
280
|
+
getIssuer, getTokenCap, getMintFeeBps,
|
|
281
|
+
getMintRequestNonce, isMinter,
|
|
282
|
+
} from "@pafi-dev/core";
|
|
283
|
+
|
|
284
|
+
// Issuer registry record (v1.6 — 7 fields)
|
|
285
|
+
const issuer = await getIssuer(provider, registry, issuerAddress);
|
|
286
|
+
// { issuerAddress, signerAddress, name, symbol, active, pointToken, mintingOracle }
|
|
287
|
+
|
|
288
|
+
// Per-token cap (v1.6 — moved off issuer struct)
|
|
289
|
+
const cap = await getTokenCap(provider, mintingOracle, pointToken);
|
|
290
|
+
// { declaredTotalSupply, capBasisPoints }
|
|
291
|
+
|
|
292
|
+
// Fee config
|
|
293
|
+
const bps = await getMintFeeBps(provider, wrapper, pointToken);
|
|
312
294
|
|
|
313
|
-
//
|
|
295
|
+
// Mint state
|
|
296
|
+
const nonce = await getMintRequestNonce(provider, pointToken, user);
|
|
297
|
+
const authorized = await isMinter(provider, pointToken, signerAddress);
|
|
314
298
|
```
|
|
315
299
|
|
|
316
|
-
|
|
317
|
-
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## v1.5 → v1.6 migration
|
|
303
|
+
|
|
304
|
+
1. `pnpm add @pafi-dev/core@latest` (≥ 0.9.6)
|
|
305
|
+
2. Replace `signMintRequest({ to, amount, nonce, deadline })` →
|
|
306
|
+
`signMintRequest({ user, receiver, amount, nonce, deadline })`
|
|
307
|
+
- Direct mint: `receiver = user`
|
|
308
|
+
- Wrapper-mediated mint: `receiver = mintFeeWrapper`
|
|
309
|
+
3. Replace `verifyMintCap(client, oracle, issuer, amount)` →
|
|
310
|
+
`verifyMintCap(client, oracle, pointToken, issuer, amount)`
|
|
311
|
+
4. Remove uses of `Issuer.declaredTotalSupply` / `Issuer.capBasisPoints`
|
|
312
|
+
— read from `getTokenCap(provider, oracle, pointToken)` instead
|
|
313
|
+
5. Drop any reference to `pafiHook` for swap fees — V4 hook removed in v1.6
|
|
314
|
+
6. Update calldata to call `mintFeeWrapper.mintWithFee(...)` when fee
|
|
315
|
+
is configured. `@pafi-dev/issuer`'s `RelayService` does this
|
|
316
|
+
automatically based on `getContractAddresses(chainId).mintFeeWrapper`
|
|
318
317
|
|
|
319
318
|
---
|
|
320
319
|
|
|
320
|
+
## References
|
|
321
|
+
|
|
322
|
+
- v1.6 deploy block: **45683465** on Base mainnet (2026-05-07)
|
|
323
|
+
- Architecture: [`ARCHITECTURE.md`](../../ARCHITECTURE.md) at SDK root
|
|
324
|
+
- Fee math: [`docs/FEE_FLOW.md`](../../../docs/FEE_FLOW.md)
|
|
325
|
+
|
|
321
326
|
## License
|
|
322
327
|
|
|
323
328
|
Apache-2.0
|
|
@@ -79,16 +79,6 @@ var burnRequestTypes = {
|
|
|
79
79
|
{ name: "deadline", type: "uint256" }
|
|
80
80
|
]
|
|
81
81
|
};
|
|
82
|
-
var receiverConsentTypes = {
|
|
83
|
-
ReceiverConsent: [
|
|
84
|
-
{ name: "onBehalfOf", type: "address" },
|
|
85
|
-
{ name: "originalReceiver", type: "address" },
|
|
86
|
-
{ name: "amount", type: "uint256" },
|
|
87
|
-
{ name: "nonce", type: "uint256" },
|
|
88
|
-
{ name: "deadline", type: "uint256" },
|
|
89
|
-
{ name: "extData", type: "bytes" }
|
|
90
|
-
]
|
|
91
|
-
};
|
|
92
82
|
var SUPPORTED_CHAINS = {
|
|
93
83
|
8453: { name: "Base" }
|
|
94
84
|
};
|
|
@@ -210,48 +200,6 @@ async function verifyBurnRequest(domain, message, signature, expectedBurner) {
|
|
|
210
200
|
return { isValid, recoveredAddress };
|
|
211
201
|
}
|
|
212
202
|
|
|
213
|
-
// src/eip712/receiverConsent.ts
|
|
214
|
-
|
|
215
|
-
function buildReceiverConsentTypedData(domain, message) {
|
|
216
|
-
return {
|
|
217
|
-
domain: buildDomain(domain),
|
|
218
|
-
types: receiverConsentTypes,
|
|
219
|
-
primaryType: "ReceiverConsent",
|
|
220
|
-
message
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
async function signReceiverConsent(walletClient, domain, message) {
|
|
224
|
-
const serialized = await walletClient.signTypedData({
|
|
225
|
-
account: walletClient.account,
|
|
226
|
-
domain: buildDomain(domain),
|
|
227
|
-
types: receiverConsentTypes,
|
|
228
|
-
primaryType: "ReceiverConsent",
|
|
229
|
-
message
|
|
230
|
-
});
|
|
231
|
-
const { v, r, s } = _viem.parseSignature.call(void 0, serialized);
|
|
232
|
-
return {
|
|
233
|
-
v: Number(v),
|
|
234
|
-
r,
|
|
235
|
-
s,
|
|
236
|
-
serialized
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
async function verifyReceiverConsent(domain, message, signature, expectedReceiver) {
|
|
240
|
-
const recoveredAddress = await _viem.recoverTypedDataAddress.call(void 0, {
|
|
241
|
-
domain: buildDomain(domain),
|
|
242
|
-
types: receiverConsentTypes,
|
|
243
|
-
primaryType: "ReceiverConsent",
|
|
244
|
-
message,
|
|
245
|
-
signature
|
|
246
|
-
});
|
|
247
|
-
const isValid = _viem.getAddress.call(void 0, recoveredAddress) === _viem.getAddress.call(void 0, expectedReceiver);
|
|
248
|
-
return { isValid, recoveredAddress };
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
203
|
|
|
256
204
|
|
|
257
205
|
|
|
@@ -273,5 +221,5 @@ async function verifyReceiverConsent(domain, message, signature, expectedReceive
|
|
|
273
221
|
|
|
274
222
|
|
|
275
223
|
|
|
276
|
-
exports.mintRequestTypes = mintRequestTypes; exports.burnRequestTypes = burnRequestTypes; exports.
|
|
277
|
-
//# sourceMappingURL=chunk-
|
|
224
|
+
exports.mintRequestTypes = mintRequestTypes; exports.burnRequestTypes = burnRequestTypes; exports.SUPPORTED_CHAINS = SUPPORTED_CHAINS; exports.V4_QUOTER_ADDRESSES = V4_QUOTER_ADDRESSES; exports.UNIVERSAL_ROUTER_ADDRESSES = UNIVERSAL_ROUTER_ADDRESSES; exports.COMMON_TOKENS = COMMON_TOKENS; exports.COMMON_POOLS = COMMON_POOLS; exports.POINT_TOKEN_POOLS = POINT_TOKEN_POOLS; exports.ENTRY_POINT_V07 = ENTRY_POINT_V07; exports.ENTRY_POINT_V08 = ENTRY_POINT_V08; exports.PERMIT2_ADDRESS = PERMIT2_ADDRESS; exports.buildDomain = buildDomain; exports.Eip712DomainMismatchError = Eip712DomainMismatchError; exports.assertDomainMatchesContract = assertDomainMatchesContract; exports.buildMintRequestTypedData = buildMintRequestTypedData; exports.signMintRequest = signMintRequest; exports.verifyMintRequest = verifyMintRequest; exports.buildBurnRequestTypedData = buildBurnRequestTypedData; exports.signBurnRequest = signBurnRequest; exports.verifyBurnRequest = verifyBurnRequest;
|
|
225
|
+
//# sourceMappingURL=chunk-4NTU7XGP.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/phitran/Pacific-Finance/pafi-backend/pafi-sdk/packages/core/dist/chunk-4NTU7XGP.cjs","../src/eip712/domain.ts","../src/eip712/mintRequest.ts","../src/constants.ts","../src/eip712/burnRequest.ts"],"names":["parseSignature","recoverTypedDataAddress","getAddress"],"mappings":"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","file":"/Users/phitran/Pacific-Finance/pafi-backend/pafi-sdk/packages/core/dist/chunk-4NTU7XGP.cjs","sourcesContent":[null,"import type { Address, PublicClient } from \"viem\";\nimport type { PointTokenDomainConfig } from \"../types\";\nimport { pointTokenAbi } from \"../abi/pointToken\";\n\n/**\n * Build the EIP-712 domain struct from a PointToken config. Uses\n * `config.version` when supplied; defaults to `\"1\"` for back-compat.\n */\nexport function buildDomain(config: PointTokenDomainConfig) {\n return {\n name: config.name,\n version: config.version ?? \"1\",\n chainId: config.chainId,\n verifyingContract: config.verifyingContract,\n };\n}\n\n/**\n * Domain mismatch error thrown by `assertDomainMatchesContract`.\n */\nexport class Eip712DomainMismatchError extends Error {\n constructor(\n public readonly field: \"name\" | \"version\" | \"chainId\" | \"verifyingContract\",\n public readonly expected: string,\n public readonly actual: string,\n ) {\n super(\n `EIP-712 domain mismatch on field \"${field}\": expected ${expected}, got ${actual}. ` +\n `Local SDK config is out of sync with deployed PointToken — signatures will be rejected on-chain. ` +\n `Update SDK config or contract before producing more signatures.`,\n );\n this.name = \"Eip712DomainMismatchError\";\n }\n}\n\n/**\n * One-RPC health check that the local EIP-712 domain config matches\n * what the deployed `PointToken` reports via `eip712Domain()`. If the\n * contract has bumped `version` from `\"1\"` to `\"2\"` (or any field\n * differs), every signature produced with the stale config will be\n * silently rejected on-chain (`ECDSA: invalid signature` — opaque to\n * the user).\n *\n * Recommended: call once at issuer-startup health check, not on every\n * mint. Throws `Eip712DomainMismatchError` describing the diverged\n * field.\n *\n * @example\n * ```ts\n * import { assertDomainMatchesContract, buildDomain } from \"@pafi-dev/core\";\n *\n * const expected = buildDomain({\n * name: \"PointToken\",\n * chainId: 8453,\n * verifyingContract: \"0x855c2046AD49AcF9B3B32557176FfCB1a1A38A22\",\n * });\n *\n * await assertDomainMatchesContract(publicClient, expected);\n * // → throws Eip712DomainMismatchError if version on-chain has bumped\n * ```\n */\nexport async function assertDomainMatchesContract(\n client: PublicClient,\n expected: ReturnType<typeof buildDomain>,\n): Promise<void> {\n const onChain = (await client.readContract({\n address: expected.verifyingContract as Address,\n abi: pointTokenAbi,\n functionName: \"eip712Domain\",\n })) as readonly [\n `0x${string}`, // fields (bytes1)\n string, // name\n string, // version\n bigint, // chainId\n Address, // verifyingContract\n `0x${string}`, // salt\n readonly bigint[], // extensions\n ];\n\n const [, name, version, chainId, verifyingContract] = onChain;\n\n if (name !== expected.name) {\n throw new Eip712DomainMismatchError(\"name\", expected.name, name);\n }\n if (version !== expected.version) {\n throw new Eip712DomainMismatchError(\n \"version\",\n expected.version,\n version,\n );\n }\n if (chainId !== BigInt(expected.chainId)) {\n throw new Eip712DomainMismatchError(\n \"chainId\",\n String(expected.chainId),\n chainId.toString(),\n );\n }\n if (\n verifyingContract.toLowerCase() !==\n expected.verifyingContract.toLowerCase()\n ) {\n throw new Eip712DomainMismatchError(\n \"verifyingContract\",\n expected.verifyingContract,\n verifyingContract,\n );\n }\n}\n","import { getAddress, parseSignature, recoverTypedDataAddress } from \"viem\";\nimport type { Address, Hex, WalletClient } from \"viem\";\nimport { mintRequestTypes } from \"../constants\";\nimport type {\n EIP712Signature,\n MintRequest,\n PointTokenDomainConfig,\n SignatureVerification,\n} from \"../types\";\nimport { buildDomain } from \"./domain\";\n\nconst PRIMARY_TYPE = \"MintForRequest\" as const;\n\n/**\n * Build the EIP-712 typed data object for a v1.6 MintForRequest.\n * Returns the standard `{ domain, types, primaryType, message }` structure\n * that any EIP-712 signer (viem, ethers, Privy, WalletConnect) can consume.\n */\nexport function buildMintRequestTypedData(\n domain: PointTokenDomainConfig,\n message: MintRequest,\n) {\n return {\n domain: buildDomain(domain),\n types: mintRequestTypes,\n primaryType: PRIMARY_TYPE,\n message,\n };\n}\n\n/**\n * Sign a v1.6 MintForRequest. Caller passes the full 5-field message:\n * - user = off-chain spender (drives nonce stream)\n * - receiver = on-chain caller (= msg.sender of `mint()`; wrapper or user)\n * - amount = PT amount\n * - nonce = pointToken.mintRequestNonces(user)\n * - deadline = unix seconds\n */\nexport async function signMintRequest(\n walletClient: WalletClient,\n domain: PointTokenDomainConfig,\n message: MintRequest,\n): Promise<EIP712Signature> {\n const serialized = await walletClient.signTypedData({\n account: walletClient.account!,\n domain: buildDomain(domain),\n types: mintRequestTypes,\n primaryType: PRIMARY_TYPE,\n message,\n });\n\n const { v, r, s } = parseSignature(serialized);\n\n return {\n v: Number(v),\n r,\n s,\n serialized,\n };\n}\n\nexport async function verifyMintRequest(\n domain: PointTokenDomainConfig,\n message: MintRequest,\n signature: Hex,\n expectedMinter: Address,\n): Promise<SignatureVerification> {\n const recoveredAddress = await recoverTypedDataAddress({\n domain: buildDomain(domain),\n types: mintRequestTypes,\n primaryType: PRIMARY_TYPE,\n message,\n signature,\n });\n\n const isValid = getAddress(recoveredAddress) === getAddress(expectedMinter);\n\n return { isValid, recoveredAddress };\n}\n","import type { Address } from \"viem\";\nimport type { ChainConfig, PoolKey } from \"./types\";\n\n// -------------------------------------------------------------------------\n// EIP-712 type definitions for viem\n// -------------------------------------------------------------------------\n\n/**\n * EIP-712 typed data for the v1.6 sig-gated mint path.\n *\n * Contract enforces:\n * - msg.sender == receiver (the on-chain caller of `mint`)\n * - nonce == mintRequestNonces[user] (per-user nonce stream)\n *\n * `user` is the off-chain spender (whose nonce advances), `receiver` is\n * the on-chain mint recipient. For direct mints `user == receiver` (user\n * calls PointToken.mint themselves). For wrapper-mediated mints `user ==\n * end-user`, `receiver == wrapper address`.\n */\nexport const mintRequestTypes = {\n MintForRequest: [\n { name: \"user\", type: \"address\" },\n { name: \"receiver\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n ],\n} as const;\n\nexport const burnRequestTypes = {\n BurnRequest: [\n { name: \"from\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n ],\n} as const;\n\n// `receiverConsentTypes` removed in v0.10 — the deployed PointToken\n// contract never had a `ReceiverConsent` path. What was conceptually\n// a \"sponsored\" mint variant is actually implemented at the relayer\n// layer (sponsor-relayer pays gas for the path-2 `MintForRequest`\n// sig-gated mint); no separate EIP-712 type or on-chain nonce mapping\n// is needed.\n\n// -------------------------------------------------------------------------\n// Chain-indexed constants — add entries here as new chains are supported\n// -------------------------------------------------------------------------\n\nexport const SUPPORTED_CHAINS: Record<number, ChainConfig> = {\n 8453: { name: \"Base\" },\n};\n\nexport const V4_QUOTER_ADDRESSES: Record<number, Address> = {\n 8453: \"0x0d5e0f971ed27fbff6c2837bf31316121532048d\",\n};\n\nexport const UNIVERSAL_ROUTER_ADDRESSES: Record<number, Address> = {\n 8453: \"0x6ff5693b99212da76ad316178a184ab56d299b43\",\n};\n\nexport const COMMON_TOKENS: Record<number, Record<string, Address>> = {\n // Base\n 8453: {\n WETH: \"0x4200000000000000000000000000000000000006\",\n USDC: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n USDT: \"0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2\",\n },\n};\n\nexport const COMMON_POOLS: Record<number, PoolKey[]> = {\n // Base — existing Uniswap V4 pools\n 8453: [\n // WETH/USDC 0.3%\n {\n currency0: \"0x4200000000000000000000000000000000000006\",\n currency1: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n fee: 3000,\n tickSpacing: 60,\n hooks: \"0x0000000000000000000000000000000000000000\",\n },\n // WETH/USDC 0.05%\n {\n currency0: \"0x4200000000000000000000000000000000000006\",\n currency1: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n fee: 500,\n tickSpacing: 10,\n hooks: \"0x0000000000000000000000000000000000000000\",\n },\n ],\n};\n\nexport const POINT_TOKEN_POOLS: Record<number, Record<Address, PoolKey[]>> = {\n // chainId → pointTokenAddress → PoolKey[]\n};\n\n// -------------------------------------------------------------------------\n// Protocol constants — chain-agnostic (same address on every EVM chain)\n// -------------------------------------------------------------------------\n\n/** ERC-4337 v0.7 EntryPoint — deployed deterministically across all EVM chains. */\nexport const ENTRY_POINT_V07: Address = \"0x0000000071727De22E5E9d8BAf0edAc6f37da032\";\n\n/**\n * ERC-4337 v0.8 EntryPoint — used by Pimlico's `Simple7702Account` impl\n * (`0xe6Cae83BdE06E4c305530e199D7217f42808555B`) and by permissionless's\n * `to7702SimpleSmartAccount`. EIP-7702 delegated EOAs in PAFI's flow\n * point at this EntryPoint, NOT v0.7.\n *\n * Why this matters: account.validateUserOp does\n * `require(msg.sender == entryPoint(), \"account: not from EntryPoint\")`.\n * If the bundler/paymaster sim runs against a different EntryPoint than\n * what the account's `entryPoint()` returns, the require fails and you\n * see `AA23 reverted account: not from EntryPoint`.\n */\nexport const ENTRY_POINT_V08: Address = \"0x4337084d9e255ff0702461cf8895ce9e3b5ff108\";\n\n/** Permit2 — Uniswap's universal approval contract, same address on all EVM chains. */\nexport const PERMIT2_ADDRESS: Address = \"0x000000000022D473030F116dDEE9F6B43aC78BA3\";\n","import { getAddress, parseSignature, recoverTypedDataAddress } from \"viem\";\nimport type { Address, Hex, WalletClient } from \"viem\";\nimport { burnRequestTypes } from \"../constants\";\nimport type {\n BurnRequest,\n EIP712Signature,\n PointTokenDomainConfig,\n SignatureVerification,\n} from \"../types\";\nimport { buildDomain } from \"./domain\";\n\n/**\n * EIP-712 helpers for `BurnRequest` — consumed by the sig-gated burn\n * path on `PointToken`:\n *\n * burn(address from, uint256 amount, uint256 deadline, bytes burnerSig)\n *\n * Solidity type hash:\n * BurnRequest(address from,uint256 amount,uint256 nonce,uint256 deadline)\n *\n * Issuer backend signs with its burner signer (HSM/KMS). On-chain\n * `msg.sender` must equal `from`, and the recovered signer must be in\n * `burners[]`. Nonce comes from `burnRequestNonces[from]` and is\n * auto-incremented on success.\n */\nexport function buildBurnRequestTypedData(\n domain: PointTokenDomainConfig,\n message: BurnRequest,\n) {\n return {\n domain: buildDomain(domain),\n types: burnRequestTypes,\n primaryType: \"BurnRequest\" as const,\n message,\n };\n}\n\nexport async function signBurnRequest(\n walletClient: WalletClient,\n domain: PointTokenDomainConfig,\n message: BurnRequest,\n): Promise<EIP712Signature> {\n const serialized = await walletClient.signTypedData({\n account: walletClient.account!,\n domain: buildDomain(domain),\n types: burnRequestTypes,\n primaryType: \"BurnRequest\",\n message,\n });\n\n const { v, r, s } = parseSignature(serialized);\n\n return {\n v: Number(v),\n r,\n s,\n serialized,\n };\n}\n\nexport async function verifyBurnRequest(\n domain: PointTokenDomainConfig,\n message: BurnRequest,\n signature: Hex,\n expectedBurner: Address,\n): Promise<SignatureVerification> {\n const recoveredAddress = await recoverTypedDataAddress({\n domain: buildDomain(domain),\n types: burnRequestTypes,\n primaryType: \"BurnRequest\",\n message,\n signature,\n });\n\n const isValid = getAddress(recoveredAddress) === getAddress(expectedBurner);\n\n return { isValid, recoveredAddress };\n}\n"]}
|
|
@@ -16,14 +16,6 @@ async function getMintRequestNonce(client, pointToken, receiver) {
|
|
|
16
16
|
args: [receiver]
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
-
async function getReceiverConsentNonce(client, pointToken, receiver) {
|
|
20
|
-
return client.readContract({
|
|
21
|
-
address: pointToken,
|
|
22
|
-
abi: _chunkKRHGFUDIcjs.pointTokenAbi,
|
|
23
|
-
functionName: "nonces",
|
|
24
|
-
args: [receiver]
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
19
|
async function isMinter(client, pointToken, account) {
|
|
28
20
|
return client.readContract({
|
|
29
21
|
address: pointToken,
|
|
@@ -176,6 +168,5 @@ async function getMintFeeRecipients(client, wrapperAddress, pointToken) {
|
|
|
176
168
|
|
|
177
169
|
|
|
178
170
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
//# sourceMappingURL=chunk-BNO5SM25.cjs.map
|
|
171
|
+
exports.getMintRequestNonce = getMintRequestNonce; exports.isMinter = isMinter; exports.getTokenName = getTokenName; exports.getIssuer = getIssuer; exports.getPointTokenBalance = getPointTokenBalance; exports.getBurnRequestNonce = getBurnRequestNonce; exports.getIssuer2 = getIssuer2; exports.issuerRegistryGetIssuerFlatAbi = issuerRegistryGetIssuerFlatAbi; exports.isActiveIssuer = isActiveIssuer; exports.verifyMintCap = verifyMintCap; exports.getPointTokenIssuer = getPointTokenIssuer; exports.getTokenCap = getTokenCap; exports.getMintFeeBps = getMintFeeBps; exports.getMintFeeRecipients = getMintFeeRecipients;
|
|
172
|
+
//# sourceMappingURL=chunk-BBQLGBOD.cjs.map
|