@bosonprotocol/x402-core 0.1.0-alpha-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/LICENSE +201 -0
- package/README.md +26 -0
- package/dist/cjs/eip712/index.d.ts +142 -0
- package/dist/cjs/eip712/index.js +224 -0
- package/dist/cjs/eip712/index.js.map +1 -0
- package/dist/cjs/eip712/token-auth/index.d.ts +259 -0
- package/dist/cjs/eip712/token-auth/index.js +221 -0
- package/dist/cjs/eip712/token-auth/index.js.map +1 -0
- package/dist/cjs/index.d.ts +15 -0
- package/dist/cjs/index.js +8 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/schemes/escrow/index.d.ts +1262 -0
- package/dist/cjs/schemes/escrow/index.js +228 -0
- package/dist/cjs/schemes/escrow/index.js.map +1 -0
- package/dist/cjs/state-machine/index.d.ts +86 -0
- package/dist/cjs/state-machine/index.js +146 -0
- package/dist/cjs/state-machine/index.js.map +1 -0
- package/dist/cjs/states-Q2FJASHh.d.ts +38 -0
- package/dist/esm/chunk-7IY3WEFZ.js +10 -0
- package/dist/esm/chunk-7IY3WEFZ.js.map +1 -0
- package/dist/esm/eip712/index.js +213 -0
- package/dist/esm/eip712/index.js.map +1 -0
- package/dist/esm/eip712/token-auth/index.js +189 -0
- package/dist/esm/eip712/token-auth/index.js.map +1 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/schemes/escrow/index.js +202 -0
- package/dist/esm/schemes/escrow/index.js.map +1 -0
- package/dist/esm/state-machine/index.js +127 -0
- package/dist/esm/state-machine/index.js.map +1 -0
- package/dist/schemas/next_actions.schema.json +87 -0
- package/dist/schemas/payment_payload.schema.json +156 -0
- package/dist/schemas/payment_requirements.schema.json +135 -0
- package/package.json +84 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { metaTx, exchanges } from '@bosonprotocol/core-sdk';
|
|
2
|
+
import { hashTypedData, recoverTypedDataAddress } from 'viem';
|
|
3
|
+
|
|
4
|
+
// src/eip712/meta-transaction.ts
|
|
5
|
+
|
|
6
|
+
// src/internal/web3lib-stub.ts
|
|
7
|
+
function unreachable(callerTag, method) {
|
|
8
|
+
return new Error(
|
|
9
|
+
`${callerTag}: stub Web3LibAdapter.${method}() should never be called. If you see this, either core-sdk changed its behaviour or the stub leaked into a non-signing-only path \u2014 file a bug.`
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
function createThrowingWeb3LibAdapter(callerTag) {
|
|
13
|
+
return {
|
|
14
|
+
uuid: `${callerTag}:stub`,
|
|
15
|
+
getSignerAddress: () => Promise.reject(unreachable(callerTag, "getSignerAddress")),
|
|
16
|
+
isSignerContract: () => Promise.reject(unreachable(callerTag, "isSignerContract")),
|
|
17
|
+
getChainId: () => Promise.reject(unreachable(callerTag, "getChainId")),
|
|
18
|
+
getBalance: () => Promise.reject(unreachable(callerTag, "getBalance")),
|
|
19
|
+
estimateGas: () => Promise.reject(unreachable(callerTag, "estimateGas")),
|
|
20
|
+
sendTransaction: () => Promise.reject(unreachable(callerTag, "sendTransaction")),
|
|
21
|
+
call: () => Promise.reject(unreachable(callerTag, "call")),
|
|
22
|
+
send: () => Promise.reject(unreachable(callerTag, "send")),
|
|
23
|
+
getTransactionReceipt: () => Promise.reject(unreachable(callerTag, "getTransactionReceipt")),
|
|
24
|
+
getCurrentTimeMs: () => Promise.reject(unreachable(callerTag, "getCurrentTimeMs"))
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function createTypedDataInterceptAdapter(args) {
|
|
28
|
+
const dummy = args.dummySignature ?? DEFAULT_DUMMY_SIGNATURE_65;
|
|
29
|
+
let captured;
|
|
30
|
+
const adapter = {
|
|
31
|
+
uuid: `${args.callerTag}:typed-data-intercept`,
|
|
32
|
+
getSignerAddress: () => Promise.resolve(args.signerAddress),
|
|
33
|
+
isSignerContract: () => Promise.resolve(false),
|
|
34
|
+
getChainId: () => Promise.resolve(args.chainId),
|
|
35
|
+
send: async (method, params) => {
|
|
36
|
+
if (method !== "eth_signTypedData_v4") {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`${args.callerTag}: unexpected RPC method during typed-data capture: ${method}`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
const json = params[1];
|
|
42
|
+
if (typeof json !== "string") {
|
|
43
|
+
throw new Error(`${args.callerTag}: eth_signTypedData_v4 payload is not a JSON string`);
|
|
44
|
+
}
|
|
45
|
+
captured = args.parse(json);
|
|
46
|
+
return dummy;
|
|
47
|
+
},
|
|
48
|
+
getBalance: () => Promise.reject(unreachable(args.callerTag, "getBalance")),
|
|
49
|
+
estimateGas: () => Promise.reject(unreachable(args.callerTag, "estimateGas")),
|
|
50
|
+
sendTransaction: () => Promise.reject(unreachable(args.callerTag, "sendTransaction")),
|
|
51
|
+
call: () => Promise.reject(unreachable(args.callerTag, "call")),
|
|
52
|
+
getTransactionReceipt: () => Promise.reject(unreachable(args.callerTag, "getTransactionReceipt")),
|
|
53
|
+
getCurrentTimeMs: () => Promise.reject(unreachable(args.callerTag, "getCurrentTimeMs"))
|
|
54
|
+
};
|
|
55
|
+
return { adapter, read: () => captured };
|
|
56
|
+
}
|
|
57
|
+
var DEFAULT_DUMMY_SIGNATURE_65 = `0x${"11".repeat(32)}${"22".repeat(32)}1b`;
|
|
58
|
+
|
|
59
|
+
// src/eip712/meta-transaction.ts
|
|
60
|
+
var META_TRANSACTION_PRIMARY_TYPE = "MetaTransaction";
|
|
61
|
+
var STUB_CALLER_TAG = "@bosonprotocol/x402-core:meta-transaction";
|
|
62
|
+
async function metaTransactionTypedData({
|
|
63
|
+
message,
|
|
64
|
+
chainId,
|
|
65
|
+
verifyingContract
|
|
66
|
+
}) {
|
|
67
|
+
const intercept = createTypedDataInterceptAdapter({
|
|
68
|
+
callerTag: STUB_CALLER_TAG,
|
|
69
|
+
// signMetaTx puts the signer's address into the `from` field of the
|
|
70
|
+
// typed-data message — we want it to match the caller-supplied `from`.
|
|
71
|
+
signerAddress: message.from,
|
|
72
|
+
chainId,
|
|
73
|
+
parse: (json) => JSON.parse(json)
|
|
74
|
+
});
|
|
75
|
+
await metaTx.handler.signMetaTx({
|
|
76
|
+
web3Lib: intercept.adapter,
|
|
77
|
+
nonce: message.nonce.toString(),
|
|
78
|
+
metaTxHandlerAddress: verifyingContract,
|
|
79
|
+
chainId,
|
|
80
|
+
functionName: message.functionName,
|
|
81
|
+
functionSignature: message.functionSignature
|
|
82
|
+
});
|
|
83
|
+
const captured = intercept.read();
|
|
84
|
+
if (!captured) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
"@bosonprotocol/x402-core:meta-transaction: signMetaTx did not invoke eth_signTypedData_v4 \u2014 core-sdk internals may have changed"
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
return captured;
|
|
90
|
+
}
|
|
91
|
+
async function hashMetaTransaction(args) {
|
|
92
|
+
const td = await metaTransactionTypedData(args);
|
|
93
|
+
return hashTypedData(td);
|
|
94
|
+
}
|
|
95
|
+
async function recoverMetaTransactionSigner(args) {
|
|
96
|
+
const { signature, ...rest } = args;
|
|
97
|
+
const td = await metaTransactionTypedData(rest);
|
|
98
|
+
return recoverTypedDataAddress({
|
|
99
|
+
domain: td.domain,
|
|
100
|
+
types: td.types,
|
|
101
|
+
primaryType: td.primaryType,
|
|
102
|
+
message: td.message,
|
|
103
|
+
signature
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
async function metaTransactionExchangeTypedData(args) {
|
|
107
|
+
return callCoreSdkForTypedData(
|
|
108
|
+
args.from,
|
|
109
|
+
args.chainId,
|
|
110
|
+
async (web3Lib) => metaTx.handler.signMetaTxRedeemVoucher({
|
|
111
|
+
web3Lib,
|
|
112
|
+
nonce: args.nonce.toString(),
|
|
113
|
+
metaTxHandlerAddress: args.verifyingContract,
|
|
114
|
+
chainId: args.chainId,
|
|
115
|
+
exchangeId: args.exchangeId.toString(),
|
|
116
|
+
returnTypedDataToSign: true
|
|
117
|
+
})
|
|
118
|
+
).then((td) => withOverriddenFunctionName(td, args.functionName));
|
|
119
|
+
}
|
|
120
|
+
async function metaTransactionDisputeResolutionTypedData(args) {
|
|
121
|
+
return callCoreSdkForTypedData(
|
|
122
|
+
args.from,
|
|
123
|
+
args.chainId,
|
|
124
|
+
async (web3Lib) => metaTx.handler.signMetaTxResolveDispute({
|
|
125
|
+
web3Lib,
|
|
126
|
+
nonce: args.nonce.toString(),
|
|
127
|
+
metaTxHandlerAddress: args.verifyingContract,
|
|
128
|
+
chainId: args.chainId,
|
|
129
|
+
exchangeId: args.exchangeId.toString(),
|
|
130
|
+
buyerPercent: args.buyerPercentBasisPoints.toString(),
|
|
131
|
+
counterpartySig: args.counterpartySig,
|
|
132
|
+
returnTypedDataToSign: true
|
|
133
|
+
})
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
async function metaTransactionFundTypedData(args) {
|
|
137
|
+
return callCoreSdkForTypedData(
|
|
138
|
+
args.from,
|
|
139
|
+
args.chainId,
|
|
140
|
+
async (web3Lib) => metaTx.handler.signMetaTxWithdrawFunds({
|
|
141
|
+
web3Lib,
|
|
142
|
+
nonce: args.nonce.toString(),
|
|
143
|
+
metaTxHandlerAddress: args.verifyingContract,
|
|
144
|
+
chainId: args.chainId,
|
|
145
|
+
entityId: args.entityId.toString(),
|
|
146
|
+
tokenList: args.tokenList,
|
|
147
|
+
tokenAmounts: args.tokenAmounts.map((amount) => amount.toString()),
|
|
148
|
+
returnTypedDataToSign: true
|
|
149
|
+
})
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
async function callCoreSdkForTypedData(from, chainId, invoke) {
|
|
153
|
+
const intercept = createTypedDataInterceptAdapter({
|
|
154
|
+
callerTag: STUB_CALLER_TAG,
|
|
155
|
+
signerAddress: from,
|
|
156
|
+
chainId,
|
|
157
|
+
// `parse` is wired up but never called — `returnTypedDataToSign: true`
|
|
158
|
+
// short-circuits in core-sdk before `eth_signTypedData_v4` would fire.
|
|
159
|
+
parse: (json) => JSON.parse(json)
|
|
160
|
+
});
|
|
161
|
+
const result = await invoke(intercept.adapter);
|
|
162
|
+
return {
|
|
163
|
+
domain: result.domain,
|
|
164
|
+
types: result.types,
|
|
165
|
+
primaryType: result.primaryType,
|
|
166
|
+
message: result.message
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function withOverriddenFunctionName(td, functionName) {
|
|
170
|
+
return {
|
|
171
|
+
...td,
|
|
172
|
+
message: { ...td.message, functionName }
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
var STUB_CALLER_TAG2 = "@bosonprotocol/x402-core:full-offer";
|
|
176
|
+
async function fullOfferTypedData({
|
|
177
|
+
fullOffer,
|
|
178
|
+
verifyingContract,
|
|
179
|
+
chainId
|
|
180
|
+
}) {
|
|
181
|
+
const sd = await exchanges.handler.signFullOffer({
|
|
182
|
+
fullOfferArgsUnsigned: fullOffer,
|
|
183
|
+
contractAddress: verifyingContract,
|
|
184
|
+
chainId,
|
|
185
|
+
web3Lib: createThrowingWeb3LibAdapter(STUB_CALLER_TAG2),
|
|
186
|
+
returnTypedDataToSign: true
|
|
187
|
+
});
|
|
188
|
+
return {
|
|
189
|
+
domain: sd.domain,
|
|
190
|
+
types: sd.types,
|
|
191
|
+
primaryType: "FullOffer",
|
|
192
|
+
message: sd.message
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
async function hashFullOffer(args) {
|
|
196
|
+
const td = await fullOfferTypedData(args);
|
|
197
|
+
return hashTypedData(td);
|
|
198
|
+
}
|
|
199
|
+
async function recoverFullOfferSigner(args) {
|
|
200
|
+
const { signature, ...rest } = args;
|
|
201
|
+
const td = await fullOfferTypedData(rest);
|
|
202
|
+
return recoverTypedDataAddress({
|
|
203
|
+
domain: td.domain,
|
|
204
|
+
types: td.types,
|
|
205
|
+
primaryType: td.primaryType,
|
|
206
|
+
message: td.message,
|
|
207
|
+
signature
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export { META_TRANSACTION_PRIMARY_TYPE, fullOfferTypedData, hashFullOffer, hashMetaTransaction, metaTransactionDisputeResolutionTypedData, metaTransactionExchangeTypedData, metaTransactionFundTypedData, metaTransactionTypedData, recoverFullOfferSigner, recoverMetaTransactionSigner };
|
|
212
|
+
//# sourceMappingURL=index.js.map
|
|
213
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/internal/web3lib-stub.ts","../../../src/eip712/meta-transaction.ts","../../../src/eip712/full-offer.ts"],"names":["STUB_CALLER_TAG","hashTypedData","recoverTypedDataAddress"],"mappings":"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","file":"index.js","sourcesContent":["// Shared stub `Web3LibAdapter` factories.\n//\n// `@bosonprotocol/core-sdk`'s signing helpers all take a `Web3LibAdapter`\n// even when no signing actually happens — e.g. `signFullOffer({\n// returnTypedDataToSign: true })` and `signMetaTx` are typed-data-only paths\n// where the adapter is structural baggage. We pass a stub adapter whose\n// methods throw if invoked, so that any future leak into a non-signing-only\n// path is loud rather than silent.\n//\n// Two flavours live here:\n//\n// - {@link createThrowingWeb3LibAdapter} — every method rejects. Used by\n// `eip712/full-offer.ts` (which truly invokes nothing).\n// - {@link createTypedDataInterceptAdapter} — captures the structured\n// data passed to `eth_signTypedData_v4` and otherwise rejects. Used by\n// `eip712/meta-transaction.ts` to extract the typed-data core-sdk\n// would otherwise ship straight to a wallet.\n//\n// This module is internal — not part of the package's public `exports`\n// map. Consumers stay on the public typed-data builders; the stubs are\n// kept here so the same loud-error idiom is shared in one place.\n//\n// {@link unreachable} is exported for callers (e.g. the intercept adapter)\n// that need to compose a custom adapter and want the same error wording.\n\nimport type { Web3LibAdapter } from \"@bosonprotocol/common\";\nimport type { Hex } from \"viem\";\n\n/** Error builder for stub methods that should never be invoked. */\nexport function unreachable(callerTag: string, method: string): Error {\n return new Error(\n `${callerTag}: stub Web3LibAdapter.${method}() should never be called. ` +\n `If you see this, either core-sdk changed its behaviour or the stub leaked ` +\n `into a non-signing-only path — file a bug.`,\n );\n}\n\n/**\n * Build a `Web3LibAdapter` whose every method rejects with {@link unreachable}.\n * `callerTag` is interpolated into the error message so the offending stub\n * site is greppable from production logs.\n */\nexport function createThrowingWeb3LibAdapter(callerTag: string): Web3LibAdapter {\n return {\n uuid: `${callerTag}:stub`,\n getSignerAddress: () => Promise.reject(unreachable(callerTag, \"getSignerAddress\")),\n isSignerContract: () => Promise.reject(unreachable(callerTag, \"isSignerContract\")),\n getChainId: () => Promise.reject(unreachable(callerTag, \"getChainId\")),\n getBalance: () => Promise.reject(unreachable(callerTag, \"getBalance\")),\n estimateGas: () => Promise.reject(unreachable(callerTag, \"estimateGas\")),\n sendTransaction: () => Promise.reject(unreachable(callerTag, \"sendTransaction\")),\n call: () => Promise.reject(unreachable(callerTag, \"call\")),\n send: () => Promise.reject(unreachable(callerTag, \"send\")),\n getTransactionReceipt: () => Promise.reject(unreachable(callerTag, \"getTransactionReceipt\")),\n getCurrentTimeMs: () => Promise.reject(unreachable(callerTag, \"getCurrentTimeMs\")),\n };\n}\n\n/** Bag returned by {@link createTypedDataInterceptAdapter}. */\nexport interface TypedDataIntercept<T> {\n adapter: Web3LibAdapter;\n /** Whatever the intercept captured, or `undefined` if `send` never fired. */\n read(): T | undefined;\n}\n\n/**\n * Build a `Web3LibAdapter` that captures the second argument to\n * `send(\"eth_signTypedData_v4\", [from, json])` (a JSON-encoded typed-data\n * object), parses it through `parse`, and stores the result for later\n * retrieval. `getSignerAddress`, `isSignerContract`, and `getChainId` are\n * answered locally so core-sdk's signing helpers don't blow up; every\n * other method rejects with {@link unreachable}.\n *\n * The 65-byte `dummySignature` returned from `send` is unused downstream —\n * core-sdk's `getSignatureParameters` only slices it without validation.\n */\nexport function createTypedDataInterceptAdapter<T>(args: {\n callerTag: string;\n signerAddress: `0x${string}`;\n chainId: number;\n parse: (jsonPayload: string) => T;\n dummySignature?: Hex;\n}): TypedDataIntercept<T> {\n const dummy = args.dummySignature ?? DEFAULT_DUMMY_SIGNATURE_65;\n let captured: T | undefined;\n\n const adapter: Web3LibAdapter = {\n uuid: `${args.callerTag}:typed-data-intercept`,\n getSignerAddress: () => Promise.resolve(args.signerAddress),\n isSignerContract: () => Promise.resolve(false),\n getChainId: () => Promise.resolve(args.chainId),\n send: async (method, params) => {\n if (method !== \"eth_signTypedData_v4\") {\n throw new Error(\n `${args.callerTag}: unexpected RPC method during typed-data capture: ${method}`,\n );\n }\n const json = (params as unknown[])[1];\n if (typeof json !== \"string\") {\n throw new Error(`${args.callerTag}: eth_signTypedData_v4 payload is not a JSON string`);\n }\n captured = args.parse(json);\n return dummy;\n },\n getBalance: () => Promise.reject(unreachable(args.callerTag, \"getBalance\")),\n estimateGas: () => Promise.reject(unreachable(args.callerTag, \"estimateGas\")),\n sendTransaction: () => Promise.reject(unreachable(args.callerTag, \"sendTransaction\")),\n call: () => Promise.reject(unreachable(args.callerTag, \"call\")),\n getTransactionReceipt: () =>\n Promise.reject(unreachable(args.callerTag, \"getTransactionReceipt\")),\n getCurrentTimeMs: () => Promise.reject(unreachable(args.callerTag, \"getCurrentTimeMs\")),\n };\n\n return { adapter, read: () => captured };\n}\n\n// Any 65-byte hex; the value is irrelevant — core-sdk's\n// `getSignatureParameters` only slices it without validation.\nconst DEFAULT_DUMMY_SIGNATURE_65: Hex = `0x${\"11\".repeat(32)}${\"22\".repeat(32)}1b`;\n","// EIP-712 typed-data builder for the Boson Protocol meta-transaction envelope.\n//\n// The MetaTransaction struct shape and the salt-flavor EIP-712 domain are\n// fully owned by `@bosonprotocol/core-sdk`'s\n// `metaTx.handler.signMetaTx`. Rather than re-declaring them here (and risking\n// drift), we route the signing call through a stub `Web3LibAdapter` that\n// intercepts `eth_signTypedData_v4` to capture the structured data, then\n// returns a dummy 65-byte signature so signMetaTx can finish without errors.\n// The intercept adapter is built by the shared\n// `createTypedDataInterceptAdapter` factory from `internal/web3lib-stub.ts`,\n// so the same loud-error semantics apply to any future helper that needs\n// to extract typed-data out of core-sdk.\n//\n// The captured object is exactly what the deployed protocol's\n// `MetaTransactionsHandlerFacet` recovers signatures against.\n//\n// The same typed-data is consumed by both:\n//\n// 1. `MetaTransactionsHandlerFacet.executeMetaTransaction(...)` — the\n// existing Boson entrypoint, already supported by `@bosonprotocol/core-sdk`.\n// Used when no token-transfer authorization payloads need to be queued\n// (e.g. `tokenAuthStrategy: \"none\"` flows where the buyer has\n// pre-approved the escrow contract).\n//\n// 2. `MetaTransactionsHandlerFacet.executeMetaTransactionWithTokenTransferAuthorization(...)`\n// — the BPIP-12 entrypoint. Used when ERC-3009 / EIP-2612 / Permit2\n// payloads are queued alongside the meta-tx.\n//\n// The buyer signs once. Choice of on-chain entrypoint is the relayer's, and\n// happens at calldata-build time downstream (in `@bosonprotocol/x402-evm`).\n\nimport { metaTx } from \"@bosonprotocol/core-sdk\";\nimport { hashTypedData, recoverTypedDataAddress, type Address, type Hex } from \"viem\";\n\nimport { createTypedDataInterceptAdapter } from \"../internal/web3lib-stub.js\";\nimport type { TypedDataField } from \"./full-offer.js\";\n\nexport const META_TRANSACTION_PRIMARY_TYPE = \"MetaTransaction\" as const;\n\n/** Strongly-typed message body — what the buyer signs. */\nexport interface MetaTransactionMessage {\n /** `MetaTransactionsHandlerFacet.usedNonce[from][nonce]` replay-protection slot. */\n nonce: bigint;\n /** Buyer EOA. Must match the signature recovery on-chain. */\n from: Address;\n /** Address of the Boson escrow contract the call targets. */\n contractAddress: Address;\n /**\n * Solidity function-name+selector string, e.g.\n * `\"createOfferCommitAndRedeem(BosonTypes.FullOffer,address,bytes,uint256)\"`.\n */\n functionName: string;\n /** ABI-encoded function-call data. */\n functionSignature: Hex;\n}\n\nexport interface MetaTransactionTypedData {\n domain: Record<string, unknown>;\n types: Record<string, readonly TypedDataField[]>;\n primaryType: typeof META_TRANSACTION_PRIMARY_TYPE;\n message: Record<string, unknown>;\n}\n\nexport interface MetaTransactionArgs {\n chainId: number;\n /** Address of the Boson escrow contract — the EIP-712 verifyingContract. */\n verifyingContract: Address;\n message: MetaTransactionMessage;\n}\n\nconst STUB_CALLER_TAG = \"@bosonprotocol/x402-core:meta-transaction\";\n\n/**\n * Build the EIP-712 typed-data for a Boson meta-transaction.\n *\n * Pass the result to:\n * - `account.signTypedData(typedData)` (a viem `LocalAccount` / HD account);\n * - `walletClient.signTypedData({ account, ...typedData })` (a viem\n * `WalletClient` for browser-wallet / RPC signers).\n *\n * Use {@link recoverMetaTransactionSigner} to verify a signature.\n */\nexport async function metaTransactionTypedData({\n message,\n chainId,\n verifyingContract,\n}: MetaTransactionArgs): Promise<MetaTransactionTypedData> {\n const intercept = createTypedDataInterceptAdapter<MetaTransactionTypedData>({\n callerTag: STUB_CALLER_TAG,\n // signMetaTx puts the signer's address into the `from` field of the\n // typed-data message — we want it to match the caller-supplied `from`.\n signerAddress: message.from,\n chainId,\n parse: (json) => JSON.parse(json) as MetaTransactionTypedData,\n });\n\n await metaTx.handler.signMetaTx({\n web3Lib: intercept.adapter,\n nonce: message.nonce.toString(),\n metaTxHandlerAddress: verifyingContract,\n chainId,\n functionName: message.functionName,\n functionSignature: message.functionSignature,\n });\n\n const captured = intercept.read();\n if (!captured) {\n throw new Error(\n \"@bosonprotocol/x402-core:meta-transaction: signMetaTx did not invoke eth_signTypedData_v4 — \" +\n \"core-sdk internals may have changed\",\n );\n }\n return captured;\n}\n\n/** EIP-712 digest for the meta-tx — what gets signed. */\nexport async function hashMetaTransaction(args: MetaTransactionArgs): Promise<Hex> {\n const td = await metaTransactionTypedData(args);\n return hashTypedData(td as Parameters<typeof hashTypedData>[0]);\n}\n\n/** Recover the signer address from a meta-tx signature. */\nexport async function recoverMetaTransactionSigner(\n args: MetaTransactionArgs & { signature: Hex },\n): Promise<Address> {\n const { signature, ...rest } = args;\n const td = await metaTransactionTypedData(rest);\n return recoverTypedDataAddress({\n domain: td.domain,\n types: td.types,\n primaryType: td.primaryType,\n message: td.message,\n signature,\n } as unknown as Parameters<typeof recoverTypedDataAddress>[0]);\n}\n\n// ===========================================================================\n// Action-specific MetaTx variants.\n//\n// core-sdk's `metaTx.handler.signMetaTx*` methods use different EIP-712\n// primary types for different action families. The recovery side MUST\n// reconstruct the same typed-data structure or `ecrecover` yields a\n// garbage address. The basic `MetaTransaction` type (handled by\n// `metaTransactionTypedData` above) only covers the commit-time actions\n// and `revokeVoucher`; the three builders below cover the rest. Each\n// routes through the corresponding core-sdk `signMetaTx*({…,\n// returnTypedDataToSign: true})` so the typed-data shape stays in\n// lock-step with the deployed protocol — no manual re-derivation of\n// types, domain, or message structure on our side.\n// ===========================================================================\n\n/** Loose typed-data shape — covers the action-specific variants below. */\nexport interface ActionMetaTransactionTypedData {\n domain: Record<string, unknown>;\n types: Record<string, readonly TypedDataField[]>;\n primaryType: string;\n message: Record<string, unknown>;\n}\n\ninterface BaseActionArgs {\n chainId: number;\n /** Address of the Boson escrow contract — the EIP-712 verifyingContract. */\n verifyingContract: Address;\n /** Boson `MetaTransactionsHandlerFacet.usedNonce[from][nonce]` replay-protection slot. */\n nonce: bigint;\n /** Buyer / signer EOA — populates the typed-data `message.from`. */\n from: Address;\n}\n\n/**\n * Build the EIP-712 typed-data for an EXCHANGE-keyed post-commit meta-tx\n * (`redeemVoucher`, `cancelVoucher`, `completeExchange`,\n * `raiseDispute`, `retractDispute`, `escalateDispute`). All six share\n * the `MetaTxExchange` primary type and `exchangeDetails: {exchangeId}`\n * sub-struct; the only difference between them is `message.functionName`.\n */\nexport async function metaTransactionExchangeTypedData(\n args: BaseActionArgs & {\n /** Boson function signature, e.g. `\"redeemVoucher(uint256)\"`. */\n functionName: string;\n /** Exchange the action targets. */\n exchangeId: bigint;\n },\n): Promise<ActionMetaTransactionTypedData> {\n return callCoreSdkForTypedData(args.from, args.chainId, async (web3Lib) =>\n metaTx.handler.signMetaTxRedeemVoucher({\n web3Lib,\n nonce: args.nonce.toString(),\n metaTxHandlerAddress: args.verifyingContract,\n chainId: args.chainId,\n exchangeId: args.exchangeId.toString(),\n returnTypedDataToSign: true,\n }),\n ).then((td) => withOverriddenFunctionName(td, args.functionName));\n}\n\n/**\n * Build the EIP-712 typed-data for `resolveDispute` — `MetaTxDisputeResolution`\n * primary type with a nested `disputeResolutionDetails` struct carrying\n * the exchange id, the buyer's percent split, and the counterparty's\n * signature.\n */\nexport async function metaTransactionDisputeResolutionTypedData(\n args: BaseActionArgs & {\n exchangeId: bigint;\n buyerPercentBasisPoints: bigint;\n /** Counterparty's signature over the resolution proposal — packed `r||s||v` hex. */\n counterpartySig: Hex;\n },\n): Promise<ActionMetaTransactionTypedData> {\n return callCoreSdkForTypedData(args.from, args.chainId, async (web3Lib) =>\n metaTx.handler.signMetaTxResolveDispute({\n web3Lib,\n nonce: args.nonce.toString(),\n metaTxHandlerAddress: args.verifyingContract,\n chainId: args.chainId,\n exchangeId: args.exchangeId.toString(),\n buyerPercent: args.buyerPercentBasisPoints.toString(),\n counterpartySig: args.counterpartySig,\n returnTypedDataToSign: true,\n }),\n );\n}\n\n/**\n * Build the EIP-712 typed-data for `withdrawFunds` — `MetaTxFund` primary\n * type with a nested `fundDetails` struct carrying the entity id, the\n * token-address list, and the per-token amounts.\n */\nexport async function metaTransactionFundTypedData(\n args: BaseActionArgs & {\n entityId: bigint;\n tokenList: readonly Address[];\n tokenAmounts: readonly bigint[];\n },\n): Promise<ActionMetaTransactionTypedData> {\n return callCoreSdkForTypedData(args.from, args.chainId, async (web3Lib) =>\n metaTx.handler.signMetaTxWithdrawFunds({\n web3Lib,\n nonce: args.nonce.toString(),\n metaTxHandlerAddress: args.verifyingContract,\n chainId: args.chainId,\n entityId: args.entityId.toString(),\n tokenList: args.tokenList as string[],\n tokenAmounts: args.tokenAmounts.map((amount) => amount.toString()),\n returnTypedDataToSign: true,\n }),\n );\n}\n\n/**\n * Drive a core-sdk `signMetaTx*({…, returnTypedDataToSign: true})` and\n * strip the convenience fields (`functionName`, `functionSignature`)\n * the SDK appends — only the EIP-712 typed-data shape is needed for\n * recovery.\n *\n * core-sdk's `returnTypedDataToSign: true` path short-circuits before\n * `eth_signTypedData_v4` is invoked, so we only need a `Web3LibAdapter`\n * that can answer `getSignerAddress()` and `getChainId()`. Any other\n * method invocation indicates core-sdk's internals changed and surfaces\n * loudly through {@link createTypedDataInterceptAdapter}'s stubs.\n */\nasync function callCoreSdkForTypedData(\n from: Address,\n chainId: number,\n invoke: (web3Lib: Parameters<typeof metaTx.handler.signMetaTx>[0][\"web3Lib\"]) => Promise<{\n domain: Record<string, unknown>;\n types: Record<string, readonly TypedDataField[]>;\n primaryType: string;\n message: Record<string, unknown>;\n }>,\n): Promise<ActionMetaTransactionTypedData> {\n const intercept = createTypedDataInterceptAdapter<ActionMetaTransactionTypedData>({\n callerTag: STUB_CALLER_TAG,\n signerAddress: from,\n chainId,\n // `parse` is wired up but never called — `returnTypedDataToSign: true`\n // short-circuits in core-sdk before `eth_signTypedData_v4` would fire.\n parse: (json) => JSON.parse(json) as ActionMetaTransactionTypedData,\n });\n const result = await invoke(intercept.adapter);\n return {\n domain: result.domain,\n types: result.types,\n primaryType: result.primaryType,\n message: result.message,\n };\n}\n\n/**\n * Substitute the typed-data's `message.functionName` for the action's\n * specific value. `metaTransactionExchangeTypedData` routes every\n * exchange-keyed action through `signMetaTxRedeemVoucher` (the six\n * methods produce identical types/domain/primaryType, differing only in\n * the hard-coded `functionName`); this override restores the correct\n * value so the recovered EIP-712 hash matches whatever the signer\n * actually signed.\n */\nfunction withOverriddenFunctionName(\n td: ActionMetaTransactionTypedData,\n functionName: string,\n): ActionMetaTransactionTypedData {\n return {\n ...td,\n message: { ...td.message, functionName },\n };\n}\n","// EIP-712 typed-data builder for the BPIP-10 FullOffer signed by the seller.\n//\n// FullOffer's nested struct shape (Offer / OfferDates / OfferDurations /\n// DRParameters / Condition / RoyaltyInfo) is large and protocol-internal — it\n// can change as the contracts evolve. Rather than hand-mirroring it here,\n// this module wraps `@bosonprotocol/core-sdk`'s\n// `exchanges.handler.signFullOffer({..., returnTypedDataToSign: true})` and\n// re-exposes the typed-data through a viem-friendly hash + recover API.\n//\n// In `returnTypedDataToSign: true` mode, core-sdk's `prepareDataSignatureParameters`\n// returns the StructuredData immediately and never invokes any method on\n// `web3Lib`. We therefore pass the shared throwing stub from\n// `internal/web3lib-stub.ts` — any future use of web3Lib is loud rather than\n// silent.\n//\n// The result hashes against the same Boson EIP-712 domain that\n// `verifyOffer` uses on-chain (salt-based, \"Boson Protocol\" name) — the\n// shape comes straight from core-sdk so we don't redefine it here.\n\nimport { exchanges } from \"@bosonprotocol/core-sdk\";\nimport type { FullOfferArgs } from \"@bosonprotocol/common\";\nimport { hashTypedData, recoverTypedDataAddress, type Address, type Hex } from \"viem\";\n\nimport { createThrowingWeb3LibAdapter } from \"../internal/web3lib-stub.js\";\n\n/** Unsigned FullOffer payload — same shape core-sdk accepts. */\nexport type UnsignedFullOffer = Omit<FullOfferArgs, \"signature\">;\n\n/** A single EIP-712 type field — a `{ name, type }` pair. */\nexport type TypedDataField = { name: string; type: string };\n\n/**\n * EIP-712 typed-data ready for any viem signer. Uses a deliberately-loose\n * `types` shape (not viem's `TypedData`) because Boson's `EIP712Domain`\n * field set is non-standard and viem's strict union rejects it; consumers\n * pass this shape directly to `hashTypedData` / `signTypedData` /\n * `recoverTypedDataAddress`, which accept it structurally.\n */\nexport interface FullOfferTypedData {\n domain: Record<string, unknown>;\n types: Record<string, readonly TypedDataField[]>;\n primaryType: \"FullOffer\";\n message: Record<string, unknown>;\n}\n\nexport interface FullOfferArgsForBuilder {\n fullOffer: UnsignedFullOffer;\n /** Address of the Boson escrow contract — the EIP-712 verifyingContract. */\n verifyingContract: Address;\n chainId: number;\n}\n\nconst STUB_CALLER_TAG = \"@bosonprotocol/x402-core:full-offer\";\n\n/**\n * Build EIP-712 typed-data for a FullOffer that the seller will sign.\n * Delegates the struct definition to `@bosonprotocol/core-sdk` so we stay in\n * lock-step with whatever shape the deployed protocol's `verifyOffer`\n * accepts.\n */\nexport async function fullOfferTypedData({\n fullOffer,\n verifyingContract,\n chainId,\n}: FullOfferArgsForBuilder): Promise<FullOfferTypedData> {\n const sd = await exchanges.handler.signFullOffer({\n fullOfferArgsUnsigned: fullOffer,\n contractAddress: verifyingContract,\n chainId,\n web3Lib: createThrowingWeb3LibAdapter(STUB_CALLER_TAG),\n returnTypedDataToSign: true,\n });\n\n return {\n domain: sd.domain as unknown as Record<string, unknown>,\n types: sd.types as unknown as Record<string, readonly TypedDataField[]>,\n primaryType: \"FullOffer\",\n message: sd.message,\n };\n}\n\n/** EIP-712 digest for a FullOffer — what the seller signs. */\nexport async function hashFullOffer(args: FullOfferArgsForBuilder): Promise<Hex> {\n const td = await fullOfferTypedData(args);\n return hashTypedData(td as Parameters<typeof hashTypedData>[0]);\n}\n\n/** Recover the seller address from a FullOffer signature. */\nexport async function recoverFullOfferSigner(\n args: FullOfferArgsForBuilder & { signature: Hex },\n): Promise<Address> {\n const { signature, ...rest } = args;\n const td = await fullOfferTypedData(rest);\n return recoverTypedDataAddress({\n domain: td.domain,\n types: td.types,\n primaryType: td.primaryType,\n message: td.message,\n signature,\n } as unknown as Parameters<typeof recoverTypedDataAddress>[0]);\n}\n"]}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { hashTypedData, recoverTypedDataAddress, encodeFunctionData } from 'viem';
|
|
2
|
+
export { createPermit2ApprovalTx, getPermit2AllowanceReadParams } from '@x402/evm/exact/client';
|
|
3
|
+
|
|
4
|
+
// src/eip712/token-auth/erc3009.ts
|
|
5
|
+
var ERC3009_TYPES = {
|
|
6
|
+
ReceiveWithAuthorization: [
|
|
7
|
+
{ name: "from", type: "address" },
|
|
8
|
+
{ name: "to", type: "address" },
|
|
9
|
+
{ name: "value", type: "uint256" },
|
|
10
|
+
{ name: "validAfter", type: "uint256" },
|
|
11
|
+
{ name: "validBefore", type: "uint256" },
|
|
12
|
+
{ name: "nonce", type: "bytes32" }
|
|
13
|
+
]
|
|
14
|
+
};
|
|
15
|
+
var ERC3009_PRIMARY_TYPE = "ReceiveWithAuthorization";
|
|
16
|
+
function erc3009TypedData({ domain, message }) {
|
|
17
|
+
return { domain, types: ERC3009_TYPES, primaryType: ERC3009_PRIMARY_TYPE, message };
|
|
18
|
+
}
|
|
19
|
+
function hashErc3009Authorization(args) {
|
|
20
|
+
return hashTypedData(erc3009TypedData(args));
|
|
21
|
+
}
|
|
22
|
+
async function recoverErc3009Signer(args) {
|
|
23
|
+
const { signature, ...rest } = args;
|
|
24
|
+
return recoverTypedDataAddress({ ...erc3009TypedData(rest), signature });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/eip712/token-auth/fetch-token-domain.ts
|
|
28
|
+
var EIP5267_ABI = [
|
|
29
|
+
{
|
|
30
|
+
type: "function",
|
|
31
|
+
name: "eip712Domain",
|
|
32
|
+
stateMutability: "view",
|
|
33
|
+
inputs: [],
|
|
34
|
+
outputs: [
|
|
35
|
+
{ name: "fields", type: "bytes1" },
|
|
36
|
+
{ name: "name", type: "string" },
|
|
37
|
+
{ name: "version", type: "string" },
|
|
38
|
+
{ name: "chainId", type: "uint256" },
|
|
39
|
+
{ name: "verifyingContract", type: "address" },
|
|
40
|
+
{ name: "salt", type: "bytes32" },
|
|
41
|
+
{ name: "extensions", type: "uint256[]" }
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
var NAME_ABI = [
|
|
46
|
+
{
|
|
47
|
+
type: "function",
|
|
48
|
+
name: "name",
|
|
49
|
+
stateMutability: "view",
|
|
50
|
+
inputs: [],
|
|
51
|
+
outputs: [{ type: "string" }]
|
|
52
|
+
}
|
|
53
|
+
];
|
|
54
|
+
var VERSION_ABI = [
|
|
55
|
+
{
|
|
56
|
+
type: "function",
|
|
57
|
+
name: "version",
|
|
58
|
+
stateMutability: "view",
|
|
59
|
+
inputs: [],
|
|
60
|
+
outputs: [{ type: "string" }]
|
|
61
|
+
}
|
|
62
|
+
];
|
|
63
|
+
var EIP5267_SALT_BIT = 16;
|
|
64
|
+
function isContractFunctionError(e) {
|
|
65
|
+
if (!(e instanceof Error)) return false;
|
|
66
|
+
return e.name.startsWith("ContractFunction");
|
|
67
|
+
}
|
|
68
|
+
async function fetchTokenDomain(publicClient, token, chainId) {
|
|
69
|
+
try {
|
|
70
|
+
const result = await publicClient.readContract({
|
|
71
|
+
address: token,
|
|
72
|
+
abi: EIP5267_ABI,
|
|
73
|
+
functionName: "eip712Domain"
|
|
74
|
+
});
|
|
75
|
+
const hasSalt = (Number(result[0]) & EIP5267_SALT_BIT) !== 0;
|
|
76
|
+
return {
|
|
77
|
+
name: result[1],
|
|
78
|
+
version: result[2],
|
|
79
|
+
chainId: Number(result[3]),
|
|
80
|
+
verifyingContract: result[4],
|
|
81
|
+
// Only attach `salt` when the bitmask says it's part of the domain
|
|
82
|
+
// — omit the key entirely rather than emitting `salt: undefined`,
|
|
83
|
+
// so the object shape matches the optional `salt?` type and
|
|
84
|
+
// downstream `in` / key checks don't see a phantom field.
|
|
85
|
+
...hasSalt ? { salt: result[5] } : {}
|
|
86
|
+
};
|
|
87
|
+
} catch (e) {
|
|
88
|
+
if (!isContractFunctionError(e)) {
|
|
89
|
+
throw e;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const name = await publicClient.readContract({
|
|
93
|
+
address: token,
|
|
94
|
+
abi: NAME_ABI,
|
|
95
|
+
functionName: "name"
|
|
96
|
+
});
|
|
97
|
+
let version = "1";
|
|
98
|
+
try {
|
|
99
|
+
version = await publicClient.readContract({
|
|
100
|
+
address: token,
|
|
101
|
+
abi: VERSION_ABI,
|
|
102
|
+
functionName: "version"
|
|
103
|
+
});
|
|
104
|
+
} catch (e) {
|
|
105
|
+
if (!isContractFunctionError(e)) {
|
|
106
|
+
throw e;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return { name, version, chainId, verifyingContract: token };
|
|
110
|
+
}
|
|
111
|
+
var PERMIT_TYPES = {
|
|
112
|
+
Permit: [
|
|
113
|
+
{ name: "owner", type: "address" },
|
|
114
|
+
{ name: "spender", type: "address" },
|
|
115
|
+
{ name: "value", type: "uint256" },
|
|
116
|
+
{ name: "nonce", type: "uint256" },
|
|
117
|
+
{ name: "deadline", type: "uint256" }
|
|
118
|
+
]
|
|
119
|
+
};
|
|
120
|
+
var PERMIT_PRIMARY_TYPE = "Permit";
|
|
121
|
+
function permitTypedData({ domain, message }) {
|
|
122
|
+
return { domain, types: PERMIT_TYPES, primaryType: PERMIT_PRIMARY_TYPE, message };
|
|
123
|
+
}
|
|
124
|
+
function hashPermit(args) {
|
|
125
|
+
return hashTypedData(permitTypedData(args));
|
|
126
|
+
}
|
|
127
|
+
async function recoverPermitSigner(args) {
|
|
128
|
+
const { signature, ...rest } = args;
|
|
129
|
+
return recoverTypedDataAddress({ ...permitTypedData(rest), signature });
|
|
130
|
+
}
|
|
131
|
+
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
132
|
+
var PERMIT2_DOMAIN_NAME = "Permit2";
|
|
133
|
+
var PERMIT2_TYPES = {
|
|
134
|
+
PermitTransferFrom: [
|
|
135
|
+
{ name: "permitted", type: "TokenPermissions" },
|
|
136
|
+
{ name: "spender", type: "address" },
|
|
137
|
+
{ name: "nonce", type: "uint256" },
|
|
138
|
+
{ name: "deadline", type: "uint256" }
|
|
139
|
+
],
|
|
140
|
+
TokenPermissions: [
|
|
141
|
+
{ name: "token", type: "address" },
|
|
142
|
+
{ name: "amount", type: "uint256" }
|
|
143
|
+
]
|
|
144
|
+
};
|
|
145
|
+
var PERMIT2_PRIMARY_TYPE = "PermitTransferFrom";
|
|
146
|
+
function permit2Domain(chainId) {
|
|
147
|
+
return { name: PERMIT2_DOMAIN_NAME, chainId, verifyingContract: PERMIT2_ADDRESS };
|
|
148
|
+
}
|
|
149
|
+
function permit2TypedData({ chainId, message }) {
|
|
150
|
+
return {
|
|
151
|
+
domain: permit2Domain(chainId),
|
|
152
|
+
types: PERMIT2_TYPES,
|
|
153
|
+
primaryType: PERMIT2_PRIMARY_TYPE,
|
|
154
|
+
message
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function hashPermit2(args) {
|
|
158
|
+
return hashTypedData(permit2TypedData(args));
|
|
159
|
+
}
|
|
160
|
+
async function recoverPermit2Signer(args) {
|
|
161
|
+
const { signature, ...rest } = args;
|
|
162
|
+
return recoverTypedDataAddress({ ...permit2TypedData(rest), signature });
|
|
163
|
+
}
|
|
164
|
+
var ERC20_APPROVE_ABI = [
|
|
165
|
+
{
|
|
166
|
+
type: "function",
|
|
167
|
+
name: "approve",
|
|
168
|
+
stateMutability: "nonpayable",
|
|
169
|
+
inputs: [
|
|
170
|
+
{ name: "spender", type: "address" },
|
|
171
|
+
{ name: "amount", type: "uint256" }
|
|
172
|
+
],
|
|
173
|
+
outputs: [{ type: "bool" }]
|
|
174
|
+
}
|
|
175
|
+
];
|
|
176
|
+
function createErc20ApprovalTx({ token, spender, amount }) {
|
|
177
|
+
return {
|
|
178
|
+
to: token,
|
|
179
|
+
data: encodeFunctionData({
|
|
180
|
+
abi: ERC20_APPROVE_ABI,
|
|
181
|
+
functionName: "approve",
|
|
182
|
+
args: [spender, amount]
|
|
183
|
+
})
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export { EIP5267_ABI, ERC3009_PRIMARY_TYPE, ERC3009_TYPES, NAME_ABI, PERMIT2_ADDRESS, PERMIT2_DOMAIN_NAME, PERMIT2_PRIMARY_TYPE, PERMIT2_TYPES, PERMIT_PRIMARY_TYPE, PERMIT_TYPES, VERSION_ABI, createErc20ApprovalTx, erc3009TypedData, fetchTokenDomain, hashErc3009Authorization, hashPermit, hashPermit2, permit2Domain, permit2TypedData, permitTypedData, recoverErc3009Signer, recoverPermit2Signer, recoverPermitSigner };
|
|
188
|
+
//# sourceMappingURL=index.js.map
|
|
189
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/eip712/token-auth/erc3009.ts","../../../../src/eip712/token-auth/fetch-token-domain.ts","../../../../src/eip712/token-auth/permit.ts","../../../../src/eip712/token-auth/permit2.ts","../../../../src/eip712/token-auth/approve.ts"],"names":["hashTypedData","recoverTypedDataAddress"],"mappings":";;;;AAsBO,IAAM,aAAA,GAAgB;AAAA,EAC3B,wBAAA,EAA0B;AAAA,IACxB,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAU;AAAA,IAChC,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,SAAA,EAAU;AAAA,IAC9B,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,SAAA,EAAU;AAAA,IACjC,EAAE,IAAA,EAAM,YAAA,EAAc,IAAA,EAAM,SAAA,EAAU;AAAA,IACtC,EAAE,IAAA,EAAM,aAAA,EAAe,IAAA,EAAM,SAAA,EAAU;AAAA,IACvC,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,SAAA;AAAU;AAErC;AAEO,IAAM,oBAAA,GAAuB;AA6B7B,SAAS,gBAAA,CAAiB,EAAE,MAAA,EAAQ,OAAA,EAAQ,EAA2C;AAC5F,EAAA,OAAO,EAAE,MAAA,EAAQ,KAAA,EAAO,aAAA,EAAe,WAAA,EAAa,sBAAsB,OAAA,EAAQ;AACpF;AAEO,SAAS,yBAAyB,IAAA,EAAiC;AACxE,EAAA,OAAO,aAAA,CAAc,gBAAA,CAAiB,IAAI,CAAC,CAAA;AAC7C;AAEA,eAAsB,qBACpB,IAAA,EACkB;AAClB,EAAA,MAAM,EAAE,SAAA,EAAW,GAAG,IAAA,EAAK,GAAI,IAAA;AAC/B,EAAA,OAAO,wBAAwB,EAAE,GAAG,iBAAiB,IAAI,CAAA,EAAG,WAAW,CAAA;AACzE;;;ACrDO,IAAM,WAAA,GAAc;AAAA,EACzB;AAAA,IACE,IAAA,EAAM,UAAA;AAAA,IACN,IAAA,EAAM,cAAA;AAAA,IACN,eAAA,EAAiB,MAAA;AAAA,IACjB,QAAQ,EAAC;AAAA,IACT,OAAA,EAAS;AAAA,MACP,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,QAAA,EAAS;AAAA,MACjC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,QAAA,EAAS;AAAA,MAC/B,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,QAAA,EAAS;AAAA,MAClC,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,SAAA,EAAU;AAAA,MACnC,EAAE,IAAA,EAAM,mBAAA,EAAqB,IAAA,EAAM,SAAA,EAAU;AAAA,MAC7C,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAU;AAAA,MAChC,EAAE,IAAA,EAAM,YAAA,EAAc,IAAA,EAAM,WAAA;AAAY;AAC1C;AAEJ;AAEO,IAAM,QAAA,GAAW;AAAA,EACtB;AAAA,IACE,IAAA,EAAM,UAAA;AAAA,IACN,IAAA,EAAM,MAAA;AAAA,IACN,eAAA,EAAiB,MAAA;AAAA,IACjB,QAAQ,EAAC;AAAA,IACT,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,UAAU;AAAA;AAEhC;AAEO,IAAM,WAAA,GAAc;AAAA,EACzB;AAAA,IACE,IAAA,EAAM,UAAA;AAAA,IACN,IAAA,EAAM,SAAA;AAAA,IACN,eAAA,EAAiB,MAAA;AAAA,IACjB,QAAQ,EAAC;AAAA,IACT,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,UAAU;AAAA;AAEhC;AASA,IAAM,gBAAA,GAAmB,EAAA;AAezB,SAAS,wBAAwB,CAAA,EAAqB;AACpD,EAAA,IAAI,EAAE,CAAA,YAAa,KAAA,CAAA,EAAQ,OAAO,KAAA;AAClC,EAAA,OAAO,CAAA,CAAE,IAAA,CAAK,UAAA,CAAW,kBAAkB,CAAA;AAC7C;AAoBA,eAAsB,gBAAA,CACpB,YAAA,EACA,KAAA,EACA,OAAA,EAC4B;AAC5B,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAU,MAAM,YAAA,CAAa,YAAA,CAAa;AAAA,MAC9C,OAAA,EAAS,KAAA;AAAA,MACT,GAAA,EAAK,WAAA;AAAA,MACL,YAAA,EAAc;AAAA,KACf,CAAA;AACD,IAAA,MAAM,WAAW,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,IAAI,gBAAA,MAAsB,CAAA;AAC3D,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,OAAO,CAAC,CAAA;AAAA,MACd,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA,MACjB,OAAA,EAAS,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,MACzB,iBAAA,EAAmB,OAAO,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAK3B,GAAI,UAAU,EAAE,IAAA,EAAM,OAAO,CAAC,CAAA,KAAM;AAAC,KACvC;AAAA,EACF,SAAS,CAAA,EAAG;AACV,IAAA,IAAI,CAAC,uBAAA,CAAwB,CAAC,CAAA,EAAG;AAC/B,MAAA,MAAM,CAAA;AAAA,IACR;AAAA,EAEF;AACA,EAAA,MAAM,IAAA,GAAQ,MAAM,YAAA,CAAa,YAAA,CAAa;AAAA,IAC5C,OAAA,EAAS,KAAA;AAAA,IACT,GAAA,EAAK,QAAA;AAAA,IACL,YAAA,EAAc;AAAA,GACf,CAAA;AACD,EAAA,IAAI,OAAA,GAAU,GAAA;AACd,EAAA,IAAI;AACF,IAAA,OAAA,GAAW,MAAM,aAAa,YAAA,CAAa;AAAA,MACzC,OAAA,EAAS,KAAA;AAAA,MACT,GAAA,EAAK,WAAA;AAAA,MACL,YAAA,EAAc;AAAA,KACf,CAAA;AAAA,EACH,SAAS,CAAA,EAAG;AACV,IAAA,IAAI,CAAC,uBAAA,CAAwB,CAAC,CAAA,EAAG;AAC/B,MAAA,MAAM,CAAA;AAAA,IACR;AAAA,EAEF;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,OAAA,EAAS,mBAAmB,KAAA,EAAM;AAC5D;ACtIO,IAAM,YAAA,GAAe;AAAA,EAC1B,MAAA,EAAQ;AAAA,IACN,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,SAAA,EAAU;AAAA,IACjC,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,SAAA,EAAU;AAAA,IACnC,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,SAAA,EAAU;AAAA,IACjC,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,SAAA,EAAU;AAAA,IACjC,EAAE,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,SAAA;AAAU;AAExC;AAEO,IAAM,mBAAA,GAAsB;AA4B5B,SAAS,eAAA,CAAgB,EAAE,MAAA,EAAQ,OAAA,EAAQ,EAAyC;AACzF,EAAA,OAAO,EAAE,MAAA,EAAQ,KAAA,EAAO,YAAA,EAAc,WAAA,EAAa,qBAAqB,OAAA,EAAQ;AAClF;AAEO,SAAS,WAAW,IAAA,EAAgC;AACzD,EAAA,OAAOA,aAAAA,CAAc,eAAA,CAAgB,IAAI,CAAC,CAAA;AAC5C;AAEA,eAAsB,oBACpB,IAAA,EACkB;AAClB,EAAA,MAAM,EAAE,SAAA,EAAW,GAAG,IAAA,EAAK,GAAI,IAAA;AAC/B,EAAA,OAAOC,wBAAwB,EAAE,GAAG,gBAAgB,IAAI,CAAA,EAAG,WAAW,CAAA;AACxE;AChCO,IAAM,eAAA,GAA2B;AAGjC,IAAM,mBAAA,GAAsB;AAE5B,IAAM,aAAA,GAAgB;AAAA,EAC3B,kBAAA,EAAoB;AAAA,IAClB,EAAE,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,kBAAA,EAAmB;AAAA,IAC9C,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,SAAA,EAAU;AAAA,IACnC,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,SAAA,EAAU;AAAA,IACjC,EAAE,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,SAAA;AAAU,GACtC;AAAA,EACA,gBAAA,EAAkB;AAAA,IAChB,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,SAAA,EAAU;AAAA,IACjC,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,SAAA;AAAU;AAEtC;AAEO,IAAM,oBAAA,GAAuB;AAuB7B,SAAS,cAAc,OAAA,EAAkC;AAC9D,EAAA,OAAO,EAAE,IAAA,EAAM,mBAAA,EAAqB,OAAA,EAAS,mBAAmB,eAAA,EAAgB;AAClF;AAEO,SAAS,gBAAA,CAAiB,EAAE,OAAA,EAAS,OAAA,EAAQ,EAA2C;AAC7F,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,cAAc,OAAO,CAAA;AAAA,IAC7B,KAAA,EAAO,aAAA;AAAA,IACP,WAAA,EAAa,oBAAA;AAAA,IACb;AAAA,GACF;AACF;AAEO,SAAS,YAAY,IAAA,EAAiC;AAC3D,EAAA,OAAOD,aAAAA,CAAc,gBAAA,CAAiB,IAAI,CAAC,CAAA;AAC7C;AAEA,eAAsB,qBACpB,IAAA,EACkB;AAClB,EAAA,MAAM,EAAE,SAAA,EAAW,GAAG,IAAA,EAAK,GAAI,IAAA;AAC/B,EAAA,OAAOC,wBAAwB,EAAE,GAAG,iBAAiB,IAAI,CAAA,EAAG,WAAW,CAAA;AACzE;AC1FA,IAAM,iBAAA,GAAoB;AAAA,EACxB;AAAA,IACE,IAAA,EAAM,UAAA;AAAA,IACN,IAAA,EAAM,SAAA;AAAA,IACN,eAAA,EAAiB,YAAA;AAAA,IACjB,MAAA,EAAQ;AAAA,MACN,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,SAAA,EAAU;AAAA,MACnC,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,SAAA;AAAU,KACpC;AAAA,IACA,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ;AAAA;AAE9B,CAAA;AAcO,SAAS,qBAAA,CAAsB,EAAE,KAAA,EAAO,OAAA,EAAS,QAAO,EAG7D;AACA,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,KAAA;AAAA,IACJ,MAAM,kBAAA,CAAmB;AAAA,MACvB,GAAA,EAAK,iBAAA;AAAA,MACL,YAAA,EAAc,SAAA;AAAA,MACd,IAAA,EAAM,CAAC,OAAA,EAAS,MAAM;AAAA,KACvB;AAAA,GACH;AACF","file":"index.js","sourcesContent":["// EIP-712 typed-data builder for ERC-3009 `ReceiveWithAuthorization`.\n//\n// Boson uses the receive variant per docs/boson-impl-01-escrow-scheme.md §4.3\n// because only the recipient (Boson escrow contract) can call\n// `receiveWithAuthorization`, eliminating relayer front-running. The struct\n// fields are identical to ERC-3009's `TransferWithAuthorization` — only the\n// on-chain function name and primary type differ. The shape is fixed by\n// EIP-3009 and hasn't changed since the standard was published.\n//\n// `@bosonprotocol/core-sdk` exposes the same type-list internally inside\n// `signReceiveWithErc3009Authorization` but auto-generates the `nonce`\n// before returning typed-data. The verification path needs a caller-supplied\n// nonce (so it can rebuild the digest the buyer signed), so this module\n// keeps a standalone typed-data builder. A KAT cross-validation test\n// (`sdk-parity.test.ts`) asserts the type-list matches the SDK's internal\n// one, catching drift if either side ever changes.\n\nimport { hashTypedData, recoverTypedDataAddress, type Address, type Hex } from \"viem\";\n\nimport type { TokenEip712Domain } from \"./domain.js\";\n\n/** EIP-712 type definition, keyed under the Boson-side primary type. */\nexport const ERC3009_TYPES = {\n ReceiveWithAuthorization: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n ],\n} as const;\n\nexport const ERC3009_PRIMARY_TYPE = \"ReceiveWithAuthorization\" as const;\n\nexport interface Erc3009Message {\n from: Address;\n to: Address;\n value: bigint;\n validAfter: bigint;\n validBefore: bigint;\n /** 32-byte hex; should be cryptographically random per the ERC-3009 spec. */\n nonce: Hex;\n}\n\nexport interface Erc3009TypedDataArgs {\n /**\n * The token contract's own EIP-712 domain. ERC-3009 requires\n * `{ name, version, chainId, verifyingContract }` to match what the\n * token recovers on-chain — see {@link TokenEip712Domain}.\n */\n domain: TokenEip712Domain;\n message: Erc3009Message;\n}\n\nexport interface Erc3009TypedData {\n domain: TokenEip712Domain;\n types: typeof ERC3009_TYPES;\n primaryType: typeof ERC3009_PRIMARY_TYPE;\n message: Erc3009Message;\n}\n\nexport function erc3009TypedData({ domain, message }: Erc3009TypedDataArgs): Erc3009TypedData {\n return { domain, types: ERC3009_TYPES, primaryType: ERC3009_PRIMARY_TYPE, message };\n}\n\nexport function hashErc3009Authorization(args: Erc3009TypedDataArgs): Hex {\n return hashTypedData(erc3009TypedData(args));\n}\n\nexport async function recoverErc3009Signer(\n args: Erc3009TypedDataArgs & { signature: Hex },\n): Promise<Address> {\n const { signature, ...rest } = args;\n return recoverTypedDataAddress({ ...erc3009TypedData(rest), signature });\n}\n","// Shared resolver for a token contract's EIP-712 domain (`name`,\n// `version`). ERC-3009 (`ReceiveWithAuthorization`) and EIP-2612\n// (`Permit`) signers and the facilitator's verify path both need this\n// lookup — keeping it in a single place ensures signing and verification\n// stay in lock-step on one ABI surface and one fallback flow.\n//\n// Tries EIP-5267's canonical `eip712Domain()` view first; on a contract\n// that doesn't implement it, falls back to ERC-20 `name()` + EIP-2612\n// `version()` with `\"1\"` as the default if `version()` reverts (the\n// EIP-2612-specified default).\n//\n// Error handling: only `ContractFunctionExecutionError` is treated as\n// \"method not implemented\" and triggers a fallback. RPC / transport\n// failures propagate as-is so callers can distinguish them and surface a\n// clear failure rather than a silent fallback that fails again on the\n// next call. `name()` is required by ERC-20 so any failure there is a\n// real error and propagates.\n\nimport { type Address, type Hex, type PublicClient } from \"viem\";\n\nimport type { TokenEip712Domain } from \"./domain.js\";\n\nexport const EIP5267_ABI = [\n {\n type: \"function\",\n name: \"eip712Domain\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [\n { name: \"fields\", type: \"bytes1\" },\n { name: \"name\", type: \"string\" },\n { name: \"version\", type: \"string\" },\n { name: \"chainId\", type: \"uint256\" },\n { name: \"verifyingContract\", type: \"address\" },\n { name: \"salt\", type: \"bytes32\" },\n { name: \"extensions\", type: \"uint256[]\" },\n ],\n },\n] as const;\n\nexport const NAME_ABI = [\n {\n type: \"function\",\n name: \"name\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ type: \"string\" }],\n },\n] as const;\n\nexport const VERSION_ABI = [\n {\n type: \"function\",\n name: \"version\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ type: \"string\" }],\n },\n] as const;\n\n// EIP-5267 `fields` bitmask: bit i (LSB-first) is set when domain field\n// i — in EIP-712's canonical field order (name, version, chainId,\n// verifyingContract, salt) — is present. We only need the `salt` bit:\n// tokens whose domain includes `salt` computed their domain separator\n// with it, so the signature won't recover unless we carry it through;\n// tokens that omit `salt` return a zero `bytes32` we must drop, or the\n// extra field corrupts the domain we hash against.\nconst EIP5267_SALT_BIT = 0x10;\n\n// Duck-type check for viem's `ContractFunctionExecutionError` (and the\n// other `ContractFunction*Error` subclasses it nests as a `cause`).\n// We compare by `.name` rather than `instanceof` because the paywall's\n// browser IIFE bundle ends up with multiple viem class instances\n// (esbuild inlines viem along several import chains —\n// `@bosonprotocol/x402-core`, `@bosonprotocol/x402-client-browser`,\n// wagmi, and direct paywall imports — and class identity is not\n// preserved across them). An `instanceof` check there would falsely\n// re-throw what's really a \"method not implemented\" revert. Name\n// strings are stable across bundles (viem sets them via\n// `Object.defineProperty(this, \"name\", ...)`) and plain `Error` from\n// transport failures still falls through to the rethrow path because\n// its `.name` is `\"Error\"`.\nfunction isContractFunctionError(e: unknown): boolean {\n if (!(e instanceof Error)) return false;\n return e.name.startsWith(\"ContractFunction\");\n}\n\n/**\n * Look up the token's EIP-712 domain. Tries EIP-5267 first (one call,\n * canonical); falls back to `name()` + `version()` (with version\n * defaulting to `\"1\"` per EIP-2612 if `version()` reverts).\n *\n * Error handling: only contract-level errors (any `ContractFunction*`\n * class viem throws via `getContractError`) are treated as \"method not\n * implemented\" and trigger the fallback. RPC / transport failures\n * (HTTP timeouts, JSON-RPC errors) propagate as-is so the caller can\n * distinguish them and surface a clear internal error rather than a\n * silent fallback that fails again on the next call. `name()` is\n * required by ERC-20 so any failure there is a real error and\n * propagates.\n *\n * Both the facilitator (recovering a signature) and the browser paywall\n * (about to sign one) call this against the same chain — keeping the\n * lookup in one place keeps signer and verifier in lockstep.\n */\nexport async function fetchTokenDomain(\n publicClient: PublicClient,\n token: Address,\n chainId: number,\n): Promise<TokenEip712Domain> {\n try {\n const result = (await publicClient.readContract({\n address: token,\n abi: EIP5267_ABI,\n functionName: \"eip712Domain\",\n })) as readonly [Hex, string, string, bigint, Address, Hex, readonly bigint[]];\n const hasSalt = (Number(result[0]) & EIP5267_SALT_BIT) !== 0;\n return {\n name: result[1],\n version: result[2],\n chainId: Number(result[3]),\n verifyingContract: result[4],\n // Only attach `salt` when the bitmask says it's part of the domain\n // — omit the key entirely rather than emitting `salt: undefined`,\n // so the object shape matches the optional `salt?` type and\n // downstream `in` / key checks don't see a phantom field.\n ...(hasSalt ? { salt: result[5] } : {}),\n };\n } catch (e) {\n if (!isContractFunctionError(e)) {\n throw e;\n }\n // EIP-5267 not implemented — fall back to name() + version().\n }\n const name = (await publicClient.readContract({\n address: token,\n abi: NAME_ABI,\n functionName: \"name\",\n })) as string;\n let version = \"1\";\n try {\n version = (await publicClient.readContract({\n address: token,\n abi: VERSION_ABI,\n functionName: \"version\",\n })) as string;\n } catch (e) {\n if (!isContractFunctionError(e)) {\n throw e;\n }\n // version() is optional per EIP-2612 — keep the default.\n }\n return { name, version, chainId, verifyingContract: token };\n}\n","// EIP-712 typed-data builder for EIP-2612 `Permit`.\n//\n// Hand-mirrors the standard 5-field shape\n// Permit(address owner, address spender, uint256 value, uint256 nonce, uint256 deadline)\n// which is identical across every well-implemented EIP-2612 token.\n//\n// `@bosonprotocol/core-sdk` exposes the same type-list internally inside\n// `signReceiveWithErc2612Permit` but auto-fetches the `nonce` from the token\n// via an on-chain `nonces(owner)` call before signing. The verification path\n// needs a caller-supplied nonce (so it can rebuild the digest the buyer\n// signed without going on-chain), so this module keeps a standalone\n// typed-data builder. A KAT cross-validation test (`sdk-parity.test.ts`)\n// asserts the type-list matches the SDK's internal one, catching drift if\n// either side ever changes.\n\nimport { hashTypedData, recoverTypedDataAddress, type Address, type Hex } from \"viem\";\n\nimport type { TokenEip712Domain } from \"./domain.js\";\n\nexport const PERMIT_TYPES = {\n Permit: [\n { name: \"owner\", type: \"address\" },\n { name: \"spender\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n ],\n} as const;\n\nexport const PERMIT_PRIMARY_TYPE = \"Permit\" as const;\n\nexport interface PermitMessage {\n owner: Address;\n spender: Address;\n value: bigint;\n /** Token-internal sequential nonce — query via `IERC20Permit.nonces(owner)`. */\n nonce: bigint;\n deadline: bigint;\n}\n\nexport interface PermitTypedDataArgs {\n /**\n * The token contract's own EIP-712 domain. EIP-2612 requires\n * `{ name, version, chainId, verifyingContract }` to produce the\n * digest the token recovers on-chain — see {@link TokenEip712Domain}.\n */\n domain: TokenEip712Domain;\n message: PermitMessage;\n}\n\nexport interface PermitTypedData {\n domain: TokenEip712Domain;\n types: typeof PERMIT_TYPES;\n primaryType: typeof PERMIT_PRIMARY_TYPE;\n message: PermitMessage;\n}\n\nexport function permitTypedData({ domain, message }: PermitTypedDataArgs): PermitTypedData {\n return { domain, types: PERMIT_TYPES, primaryType: PERMIT_PRIMARY_TYPE, message };\n}\n\nexport function hashPermit(args: PermitTypedDataArgs): Hex {\n return hashTypedData(permitTypedData(args));\n}\n\nexport async function recoverPermitSigner(\n args: PermitTypedDataArgs & { signature: Hex },\n): Promise<Address> {\n const { signature, ...rest } = args;\n return recoverTypedDataAddress({ ...permitTypedData(rest), signature });\n}\n","// EIP-712 typed-data builder for Uniswap Permit2 `PermitTransferFrom`.\n//\n// Boson uses the no-witness `PermitTransferFrom` flavor per\n// docs/boson-impl-01-escrow-scheme.md §4.3 (the witness-bearing\n// `PermitWitnessTransferFrom` variant is for x402's exact scheme, which\n// pins the recipient inside the witness — Boson doesn't need that since\n// the escrow contract is the only valid recipient anyway).\n//\n// `@bosonprotocol/core-sdk` exposes the same type-list internally inside\n// `signReceiveWithPermit2`, but routes the Permit2 contract address through\n// `_contracts.permit2` (or `overrides.permit2Address`) on the configured\n// SDK instance. The verification path needs a stable canonical address\n// without an SDK round-trip, and the type-list is fixed by Permit2's\n// deployed contract — so this module keeps the canonical address +\n// type-list hand-defined as Uniswap protocol constants. A KAT\n// cross-validation test (`sdk-parity.test.ts`) asserts the type-list\n// matches the SDK's internal one, catching drift.\n//\n// `@x402/evm`'s public `./exact/client` exposes `createPermit2ApprovalTx`\n// and `getPermit2AllowanceReadParams` (re-exported below).\n\nimport { createPermit2ApprovalTx, getPermit2AllowanceReadParams } from \"@x402/evm/exact/client\";\nimport {\n hashTypedData,\n recoverTypedDataAddress,\n type Address,\n type Hex,\n type TypedDataDomain,\n} from \"viem\";\n\nexport { createPermit2ApprovalTx, getPermit2AllowanceReadParams };\n\n/**\n * Canonical Permit2 contract address. Same on every EVM chain via CREATE2\n * deployment.\n *\n * @see https://github.com/Uniswap/permit2\n */\nexport const PERMIT2_ADDRESS: Address = \"0x000000000022D473030F116dDEE9F6B43aC78BA3\";\n\n/** Permit2's EIP-712 `name` field. No `version`, no `salt`. */\nexport const PERMIT2_DOMAIN_NAME = \"Permit2\" as const;\n\nexport const PERMIT2_TYPES = {\n PermitTransferFrom: [\n { name: \"permitted\", type: \"TokenPermissions\" },\n { name: \"spender\", type: \"address\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n ],\n TokenPermissions: [\n { name: \"token\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n} as const;\n\nexport const PERMIT2_PRIMARY_TYPE = \"PermitTransferFrom\" as const;\n\nexport interface Permit2Message {\n permitted: { token: Address; amount: bigint };\n spender: Address;\n /** Permit2 word-bitmap nonce. */\n nonce: bigint;\n deadline: bigint;\n}\n\nexport interface Permit2TypedDataArgs {\n chainId: number;\n message: Permit2Message;\n}\n\nexport interface Permit2TypedData {\n domain: TypedDataDomain;\n types: typeof PERMIT2_TYPES;\n primaryType: typeof PERMIT2_PRIMARY_TYPE;\n message: Permit2Message;\n}\n\n/** Permit2's EIP-712 domain on a given chain. The `verifyingContract` is the canonical Permit2 address. */\nexport function permit2Domain(chainId: number): TypedDataDomain {\n return { name: PERMIT2_DOMAIN_NAME, chainId, verifyingContract: PERMIT2_ADDRESS };\n}\n\nexport function permit2TypedData({ chainId, message }: Permit2TypedDataArgs): Permit2TypedData {\n return {\n domain: permit2Domain(chainId),\n types: PERMIT2_TYPES,\n primaryType: PERMIT2_PRIMARY_TYPE,\n message,\n };\n}\n\nexport function hashPermit2(args: Permit2TypedDataArgs): Hex {\n return hashTypedData(permit2TypedData(args));\n}\n\nexport async function recoverPermit2Signer(\n args: Permit2TypedDataArgs & { signature: Hex },\n): Promise<Address> {\n const { signature, ...rest } = args;\n return recoverTypedDataAddress({ ...permit2TypedData(rest), signature });\n}\n","// Helper for the `tokenAuthStrategy: \"none\"` flow (per\n// docs/boson-impl-01-escrow-scheme.md §4.3): the buyer must pre-approve\n// the Boson escrow contract to spend `amount` of `token` via the standard\n// ERC-20 `approve(spender, amount)` call.\n//\n// No EIP-712 typed-data is signed for this strategy; the buyer instead\n// sends a regular ERC-20 transaction. This module just builds the calldata\n// so callers can hand it to a wallet client.\n\nimport { encodeFunctionData, type Address, type Hex } from \"viem\";\n\nconst ERC20_APPROVE_ABI = [\n {\n type: \"function\",\n name: \"approve\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"spender\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [{ type: \"bool\" }],\n },\n] as const;\n\nexport interface Erc20ApprovalArgs {\n token: Address;\n spender: Address;\n amount: bigint;\n}\n\n/**\n * Build calldata for an ERC-20 `approve(spender, amount)` call. Use with\n * `walletClient.sendTransaction({ to: token, data })` or any equivalent\n * signer to grant `spender` (the Boson escrow contract) the right to\n * pull `amount` of `token`.\n */\nexport function createErc20ApprovalTx({ token, spender, amount }: Erc20ApprovalArgs): {\n to: Address;\n data: Hex;\n} {\n return {\n to: token,\n data: encodeFunctionData({\n abi: ERC20_APPROVE_ABI,\n functionName: \"approve\",\n args: [spender, amount],\n }),\n };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/headers.ts"],"names":[],"mappings":";AAiBO,IAAM,iBAAA,GAAoB","file":"index.js","sourcesContent":["// Shared HTTP header names that span the buyer-side fetch wrapper and\n// any resource server / facilitator implementing the x402B escrow\n// scheme. Centralising them here keeps the wire contract single-sourced\n// across packages.\n\n/**\n * Custom header `@bosonprotocol/x402-client-fetch` stamps on both the\n * initial request and the X-PAYMENT retry. Resource servers that scope\n * their `FullOffer` cache per buyer flow key the cache off this id so\n * the 402 challenge and the X-PAYMENT retry share one signed offer.\n *\n * The canonical value uses mixed case for header readability; HTTP\n * header lookups are case-insensitive on both Node (`req.headers[…]`\n * are already lowercased) and Express (`req.header(…)`), so importers\n * can pass the constant verbatim regardless of which lookup style they\n * use.\n */\nexport const SESSION_ID_HEADER = \"X-X402-Boson-Session-Id\";\n"]}
|