thirdweb 5.108.2 → 5.108.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/exports/x402.js.map +1 -1
- package/dist/cjs/extensions/erc20/__generated__/USDC/write/transferWithAuthorization.js +176 -0
- package/dist/cjs/extensions/erc20/__generated__/USDC/write/transferWithAuthorization.js.map +1 -0
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/x402/common.js +39 -1
- package/dist/cjs/x402/common.js.map +1 -1
- package/dist/cjs/x402/facilitator.js +1 -0
- package/dist/cjs/x402/facilitator.js.map +1 -1
- package/dist/cjs/x402/fetchWithPayment.js +2 -2
- package/dist/cjs/x402/fetchWithPayment.js.map +1 -1
- package/dist/cjs/x402/sign.js +100 -34
- package/dist/cjs/x402/sign.js.map +1 -1
- package/dist/cjs/x402/types.js.map +1 -1
- package/dist/esm/exports/x402.js.map +1 -1
- package/dist/esm/extensions/erc20/__generated__/USDC/write/transferWithAuthorization.js +169 -0
- package/dist/esm/extensions/erc20/__generated__/USDC/write/transferWithAuthorization.js.map +1 -0
- package/dist/esm/version.js +1 -1
- package/dist/esm/x402/common.js +38 -1
- package/dist/esm/x402/common.js.map +1 -1
- package/dist/esm/x402/facilitator.js +1 -0
- package/dist/esm/x402/facilitator.js.map +1 -1
- package/dist/esm/x402/fetchWithPayment.js +2 -2
- package/dist/esm/x402/fetchWithPayment.js.map +1 -1
- package/dist/esm/x402/sign.js +100 -34
- package/dist/esm/x402/sign.js.map +1 -1
- package/dist/esm/x402/types.js.map +1 -1
- package/dist/scripts/bridge-widget.js +2 -2
- package/dist/types/exports/x402.d.ts +1 -1
- package/dist/types/exports/x402.d.ts.map +1 -1
- package/dist/types/extensions/erc20/__generated__/USDC/write/transferWithAuthorization.d.ts +121 -0
- package/dist/types/extensions/erc20/__generated__/USDC/write/transferWithAuthorization.d.ts.map +1 -0
- package/dist/types/react/web/ui/Bridge/swap-widget/SwapWidget.d.ts +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/x402/common.d.ts +8 -1
- package/dist/types/x402/common.d.ts.map +1 -1
- package/dist/types/x402/facilitator.d.ts +18 -41
- package/dist/types/x402/facilitator.d.ts.map +1 -1
- package/dist/types/x402/fetchWithPayment.d.ts +1 -1
- package/dist/types/x402/fetchWithPayment.d.ts.map +1 -1
- package/dist/types/x402/sign.d.ts +2 -1
- package/dist/types/x402/sign.d.ts.map +1 -1
- package/dist/types/x402/types.d.ts +16 -3
- package/dist/types/x402/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/exports/x402.ts +1 -0
- package/src/extensions/erc20/__generated__/USDC/write/transferWithAuthorization.ts +215 -0
- package/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsx +1 -1
- package/src/version.ts +1 -1
- package/src/x402/common.ts +58 -5
- package/src/x402/facilitator.ts +28 -1
- package/src/x402/fetchWithPayment.ts +3 -2
- package/src/x402/sign.ts +140 -49
- package/src/x402/types.ts +18 -7
package/src/x402/common.ts
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Abi } from "abitype";
|
|
2
|
+
import { toFunctionSelector } from "viem/utils";
|
|
3
|
+
import { type Money, moneySchema } from "x402/types";
|
|
4
|
+
import { getCachedChain } from "../chains/utils.js";
|
|
5
|
+
import type { ThirdwebClient } from "../client/client.js";
|
|
6
|
+
import { resolveContractAbi } from "../contract/actions/resolve-abi.js";
|
|
7
|
+
import { getContract } from "../contract/contract.js";
|
|
8
|
+
import { isPermitSupported } from "../extensions/erc20/__generated__/IERC20Permit/write/permit.js";
|
|
9
|
+
import { isTransferWithAuthorizationSupported } from "../extensions/erc20/__generated__/USDC/write/transferWithAuthorization.js";
|
|
2
10
|
import { getAddress } from "../utils/address.js";
|
|
3
11
|
import { decodePayment } from "./encode.js";
|
|
4
|
-
import type {
|
|
12
|
+
import type { ThirdwebX402Facilitator } from "./facilitator.js";
|
|
5
13
|
import {
|
|
6
14
|
networkToChainId,
|
|
7
15
|
type RequestedPaymentPayload,
|
|
8
16
|
type RequestedPaymentRequirements,
|
|
9
17
|
} from "./schemas.js";
|
|
10
18
|
import {
|
|
19
|
+
type ERC20TokenAmount,
|
|
11
20
|
type PaymentArgs,
|
|
12
21
|
type PaymentRequiredResult,
|
|
22
|
+
type SupportedSignatureType,
|
|
13
23
|
x402Version,
|
|
14
24
|
} from "./types.js";
|
|
15
25
|
|
|
@@ -106,7 +116,10 @@ export async function decodePaymentRequest(
|
|
|
106
116
|
},
|
|
107
117
|
output: outputSchema,
|
|
108
118
|
},
|
|
109
|
-
extra:
|
|
119
|
+
extra: {
|
|
120
|
+
facilitatorAddress: facilitator.address,
|
|
121
|
+
...((asset as ERC20TokenAmount["asset"]).eip712 ?? {}),
|
|
122
|
+
},
|
|
110
123
|
});
|
|
111
124
|
|
|
112
125
|
// Check for payment header
|
|
@@ -184,7 +197,7 @@ export async function decodePaymentRequest(
|
|
|
184
197
|
async function processPriceToAtomicAmount(
|
|
185
198
|
price: Money | ERC20TokenAmount,
|
|
186
199
|
chainId: number,
|
|
187
|
-
facilitator:
|
|
200
|
+
facilitator: ThirdwebX402Facilitator,
|
|
188
201
|
): Promise<
|
|
189
202
|
| { maxAmountRequired: string; asset: ERC20TokenAmount["asset"] }
|
|
190
203
|
| { error: string }
|
|
@@ -224,7 +237,7 @@ async function processPriceToAtomicAmount(
|
|
|
224
237
|
|
|
225
238
|
async function getDefaultAsset(
|
|
226
239
|
chainId: number,
|
|
227
|
-
facilitator:
|
|
240
|
+
facilitator: ThirdwebX402Facilitator,
|
|
228
241
|
): Promise<ERC20TokenAmount["asset"] | undefined> {
|
|
229
242
|
const supportedAssets = await facilitator.supported();
|
|
230
243
|
const matchingAsset = supportedAssets.kinds.find(
|
|
@@ -234,3 +247,43 @@ async function getDefaultAsset(
|
|
|
234
247
|
?.defaultAsset as ERC20TokenAmount["asset"];
|
|
235
248
|
return assetConfig;
|
|
236
249
|
}
|
|
250
|
+
|
|
251
|
+
export async function getSupportedSignatureType(args: {
|
|
252
|
+
client: ThirdwebClient;
|
|
253
|
+
asset: string;
|
|
254
|
+
chainId: number;
|
|
255
|
+
eip712Extras: ERC20TokenAmount["asset"]["eip712"] | undefined;
|
|
256
|
+
}): Promise<SupportedSignatureType | undefined> {
|
|
257
|
+
const primaryType = args.eip712Extras?.primaryType;
|
|
258
|
+
|
|
259
|
+
if (primaryType === "Permit" || primaryType === "TransferWithAuthorization") {
|
|
260
|
+
return primaryType;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// not specified, so we need to detect it
|
|
264
|
+
const abi = await resolveContractAbi<Abi>(
|
|
265
|
+
getContract({
|
|
266
|
+
client: args.client,
|
|
267
|
+
address: args.asset,
|
|
268
|
+
chain: getCachedChain(args.chainId),
|
|
269
|
+
}),
|
|
270
|
+
).catch((error) => {
|
|
271
|
+
console.error("Error resolving contract ABI", error);
|
|
272
|
+
return [] as Abi;
|
|
273
|
+
});
|
|
274
|
+
const selectors = abi
|
|
275
|
+
.filter((f) => f.type === "function")
|
|
276
|
+
.map((f) => toFunctionSelector(f));
|
|
277
|
+
const hasPermit = isPermitSupported(selectors);
|
|
278
|
+
const hasTransferWithAuthorization =
|
|
279
|
+
isTransferWithAuthorizationSupported(selectors);
|
|
280
|
+
|
|
281
|
+
// prefer transferWithAuthorization over permit
|
|
282
|
+
if (hasTransferWithAuthorization) {
|
|
283
|
+
return "TransferWithAuthorization";
|
|
284
|
+
}
|
|
285
|
+
if (hasPermit) {
|
|
286
|
+
return "Permit";
|
|
287
|
+
}
|
|
288
|
+
return undefined;
|
|
289
|
+
}
|
package/src/x402/facilitator.ts
CHANGED
|
@@ -15,6 +15,30 @@ export type ThirdwebX402FacilitatorConfig = {
|
|
|
15
15
|
baseUrl?: string;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* facilitator for the x402 payment protocol.
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
export type ThirdwebX402Facilitator = {
|
|
23
|
+
url: `${string}://${string}`;
|
|
24
|
+
address: string;
|
|
25
|
+
createAuthHeaders: () => Promise<{
|
|
26
|
+
verify: Record<string, string>;
|
|
27
|
+
settle: Record<string, string>;
|
|
28
|
+
supported: Record<string, string>;
|
|
29
|
+
list: Record<string, string>;
|
|
30
|
+
}>;
|
|
31
|
+
verify: (
|
|
32
|
+
payload: RequestedPaymentPayload,
|
|
33
|
+
paymentRequirements: RequestedPaymentRequirements,
|
|
34
|
+
) => Promise<VerifyResponse>;
|
|
35
|
+
settle: (
|
|
36
|
+
payload: RequestedPaymentPayload,
|
|
37
|
+
paymentRequirements: RequestedPaymentRequirements,
|
|
38
|
+
) => Promise<FacilitatorSettleResponse>;
|
|
39
|
+
supported: () => Promise<SupportedPaymentKindsResponse>;
|
|
40
|
+
};
|
|
41
|
+
|
|
18
42
|
const DEFAULT_BASE_URL = "https://api.thirdweb.com/v1/payments/x402";
|
|
19
43
|
|
|
20
44
|
/**
|
|
@@ -56,7 +80,9 @@ const DEFAULT_BASE_URL = "https://api.thirdweb.com/v1/payments/x402";
|
|
|
56
80
|
*
|
|
57
81
|
* @bridge x402
|
|
58
82
|
*/
|
|
59
|
-
export function facilitator(
|
|
83
|
+
export function facilitator(
|
|
84
|
+
config: ThirdwebX402FacilitatorConfig,
|
|
85
|
+
): ThirdwebX402Facilitator {
|
|
60
86
|
const secretKey = config.client.secretKey;
|
|
61
87
|
if (!secretKey) {
|
|
62
88
|
throw new Error("Client secret key is required for the x402 facilitator");
|
|
@@ -69,6 +95,7 @@ export function facilitator(config: ThirdwebX402FacilitatorConfig) {
|
|
|
69
95
|
}
|
|
70
96
|
const facilitator = {
|
|
71
97
|
url: (config.baseUrl ?? DEFAULT_BASE_URL) as `${string}://${string}`,
|
|
98
|
+
address: serverWalletAddress,
|
|
72
99
|
createAuthHeaders: async () => {
|
|
73
100
|
return {
|
|
74
101
|
verify: {
|
|
@@ -50,7 +50,7 @@ import { createPaymentHeader } from "./sign.js";
|
|
|
50
50
|
*/
|
|
51
51
|
export function wrapFetchWithPayment(
|
|
52
52
|
fetch: typeof globalThis.fetch,
|
|
53
|
-
|
|
53
|
+
client: ThirdwebClient,
|
|
54
54
|
wallet: Wallet,
|
|
55
55
|
maxValue: bigint = BigInt(1 * 10 ** 6), // Default to 1 USDC
|
|
56
56
|
) {
|
|
@@ -103,9 +103,10 @@ export function wrapFetchWithPayment(
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
const paymentHeader = await createPaymentHeader(
|
|
106
|
+
client,
|
|
106
107
|
account,
|
|
107
|
-
x402Version,
|
|
108
108
|
selectedPaymentRequirements,
|
|
109
|
+
x402Version,
|
|
109
110
|
);
|
|
110
111
|
|
|
111
112
|
const initParams = init || {};
|
package/src/x402/sign.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
import { hexToBigInt } from "viem";
|
|
1
2
|
import type { ExactEvmPayloadAuthorization } from "x402/types";
|
|
3
|
+
import { getCachedChain } from "../chains/utils.js";
|
|
4
|
+
import type { ThirdwebClient } from "../client/client.js";
|
|
5
|
+
import { getContract } from "../contract/contract.js";
|
|
6
|
+
import { nonces } from "../extensions/erc20/__generated__/IERC20Permit/read/nonces.js";
|
|
2
7
|
import { type Address, getAddress } from "../utils/address.js";
|
|
3
8
|
import { type Hex, toHex } from "../utils/encoding/hex.js";
|
|
4
9
|
import type { Account } from "../wallets/interfaces/wallet.js";
|
|
10
|
+
import { getSupportedSignatureType } from "./common.js";
|
|
5
11
|
import { encodePayment } from "./encode.js";
|
|
6
12
|
import {
|
|
7
13
|
networkToChainId,
|
|
@@ -9,6 +15,7 @@ import {
|
|
|
9
15
|
type RequestedPaymentRequirements,
|
|
10
16
|
type UnsignedPaymentPayload,
|
|
11
17
|
} from "./schemas.js";
|
|
18
|
+
import type { ERC20TokenAmount } from "./types.js";
|
|
12
19
|
|
|
13
20
|
/**
|
|
14
21
|
* Prepares an unsigned payment header with the given sender address and payment requirements.
|
|
@@ -22,9 +29,8 @@ function preparePaymentHeader(
|
|
|
22
29
|
from: Address,
|
|
23
30
|
x402Version: number,
|
|
24
31
|
paymentRequirements: RequestedPaymentRequirements,
|
|
32
|
+
nonce: Hex,
|
|
25
33
|
): UnsignedPaymentPayload {
|
|
26
|
-
const nonce = createNonce();
|
|
27
|
-
|
|
28
34
|
const validAfter = BigInt(
|
|
29
35
|
Math.floor(Date.now() / 1000) - 600, // 10 minutes before
|
|
30
36
|
).toString();
|
|
@@ -44,7 +50,7 @@ function preparePaymentHeader(
|
|
|
44
50
|
value: paymentRequirements.maxAmountRequired,
|
|
45
51
|
validAfter: validAfter.toString(),
|
|
46
52
|
validBefore: validBefore.toString(),
|
|
47
|
-
nonce,
|
|
53
|
+
nonce: nonce,
|
|
48
54
|
},
|
|
49
55
|
},
|
|
50
56
|
};
|
|
@@ -59,45 +65,78 @@ function preparePaymentHeader(
|
|
|
59
65
|
* @returns A promise that resolves to the signed payment payload
|
|
60
66
|
*/
|
|
61
67
|
async function signPaymentHeader(
|
|
68
|
+
client: ThirdwebClient,
|
|
62
69
|
account: Account,
|
|
63
70
|
paymentRequirements: RequestedPaymentRequirements,
|
|
64
|
-
unsignedPaymentHeader: UnsignedPaymentPayload,
|
|
65
|
-
): Promise<RequestedPaymentPayload> {
|
|
66
|
-
const { signature } = await signAuthorization(
|
|
67
|
-
account,
|
|
68
|
-
unsignedPaymentHeader.payload.authorization,
|
|
69
|
-
paymentRequirements,
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
...unsignedPaymentHeader,
|
|
74
|
-
payload: {
|
|
75
|
-
...unsignedPaymentHeader.payload,
|
|
76
|
-
signature,
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Creates a complete payment payload by preparing and signing a payment header.
|
|
83
|
-
*
|
|
84
|
-
* @param client - The signer wallet instance used to create and sign the payment
|
|
85
|
-
* @param x402Version - The version of the X402 protocol to use
|
|
86
|
-
* @param paymentRequirements - The payment requirements containing scheme and network information
|
|
87
|
-
* @returns A promise that resolves to the complete signed payment payload
|
|
88
|
-
*/
|
|
89
|
-
async function createPayment(
|
|
90
|
-
account: Account,
|
|
91
71
|
x402Version: number,
|
|
92
|
-
paymentRequirements: RequestedPaymentRequirements,
|
|
93
72
|
): Promise<RequestedPaymentPayload> {
|
|
94
73
|
const from = getAddress(account.address);
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
paymentRequirements,
|
|
99
|
-
|
|
100
|
-
|
|
74
|
+
const chainId = networkToChainId(paymentRequirements.network);
|
|
75
|
+
const supportedSignatureType = await getSupportedSignatureType({
|
|
76
|
+
client,
|
|
77
|
+
asset: paymentRequirements.asset,
|
|
78
|
+
chainId: chainId,
|
|
79
|
+
eip712Extras: paymentRequirements.extra as
|
|
80
|
+
| ERC20TokenAmount["asset"]["eip712"]
|
|
81
|
+
| undefined,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
switch (supportedSignatureType) {
|
|
85
|
+
case "Permit": {
|
|
86
|
+
const nonce = await nonces({
|
|
87
|
+
contract: getContract({
|
|
88
|
+
address: paymentRequirements.asset,
|
|
89
|
+
chain: getCachedChain(chainId),
|
|
90
|
+
client: client,
|
|
91
|
+
}),
|
|
92
|
+
owner: from,
|
|
93
|
+
});
|
|
94
|
+
const unsignedPaymentHeader = preparePaymentHeader(
|
|
95
|
+
from,
|
|
96
|
+
x402Version,
|
|
97
|
+
paymentRequirements,
|
|
98
|
+
toHex(nonce, { size: 32 }), // permit nonce
|
|
99
|
+
);
|
|
100
|
+
const { signature } = await signERC2612Permit(
|
|
101
|
+
account,
|
|
102
|
+
unsignedPaymentHeader.payload.authorization,
|
|
103
|
+
paymentRequirements,
|
|
104
|
+
);
|
|
105
|
+
return {
|
|
106
|
+
...unsignedPaymentHeader,
|
|
107
|
+
payload: {
|
|
108
|
+
...unsignedPaymentHeader.payload,
|
|
109
|
+
signature,
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
case "TransferWithAuthorization": {
|
|
114
|
+
// default to transfer with authorization
|
|
115
|
+
const nonce = await createNonce();
|
|
116
|
+
const unsignedPaymentHeader = preparePaymentHeader(
|
|
117
|
+
from,
|
|
118
|
+
x402Version,
|
|
119
|
+
paymentRequirements,
|
|
120
|
+
nonce, // random nonce
|
|
121
|
+
);
|
|
122
|
+
const { signature } = await signERC3009Authorization(
|
|
123
|
+
account,
|
|
124
|
+
unsignedPaymentHeader.payload.authorization,
|
|
125
|
+
paymentRequirements,
|
|
126
|
+
);
|
|
127
|
+
return {
|
|
128
|
+
...unsignedPaymentHeader,
|
|
129
|
+
payload: {
|
|
130
|
+
...unsignedPaymentHeader.payload,
|
|
131
|
+
signature,
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
default:
|
|
136
|
+
throw new Error(
|
|
137
|
+
`No supported payment authorization methods found on ${paymentRequirements.asset} on chain ${paymentRequirements.network}`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
101
140
|
}
|
|
102
141
|
|
|
103
142
|
/**
|
|
@@ -109,14 +148,16 @@ async function createPayment(
|
|
|
109
148
|
* @returns A promise that resolves to the encoded payment header string
|
|
110
149
|
*/
|
|
111
150
|
export async function createPaymentHeader(
|
|
151
|
+
client: ThirdwebClient,
|
|
112
152
|
account: Account,
|
|
113
|
-
x402Version: number,
|
|
114
153
|
paymentRequirements: RequestedPaymentRequirements,
|
|
154
|
+
x402Version: number,
|
|
115
155
|
): Promise<string> {
|
|
116
|
-
const payment = await
|
|
156
|
+
const payment = await signPaymentHeader(
|
|
157
|
+
client,
|
|
117
158
|
account,
|
|
118
|
-
x402Version,
|
|
119
159
|
paymentRequirements,
|
|
160
|
+
x402Version,
|
|
120
161
|
);
|
|
121
162
|
return encodePayment(payment);
|
|
122
163
|
}
|
|
@@ -138,7 +179,7 @@ export async function createPaymentHeader(
|
|
|
138
179
|
* @param paymentRequirements.extra - The extra information containing the name and version of the ERC20 contract
|
|
139
180
|
* @returns The signature for the authorization
|
|
140
181
|
*/
|
|
141
|
-
async function
|
|
182
|
+
async function signERC3009Authorization(
|
|
142
183
|
account: Account,
|
|
143
184
|
{
|
|
144
185
|
from,
|
|
@@ -154,8 +195,7 @@ async function signAuthorization(
|
|
|
154
195
|
const name = extra?.name;
|
|
155
196
|
const version = extra?.version;
|
|
156
197
|
|
|
157
|
-
|
|
158
|
-
const data = {
|
|
198
|
+
const signature = await account.signTypedData({
|
|
159
199
|
types: {
|
|
160
200
|
TransferWithAuthorization: [
|
|
161
201
|
{ name: "from", type: "address" },
|
|
@@ -176,14 +216,65 @@ async function signAuthorization(
|
|
|
176
216
|
message: {
|
|
177
217
|
from: getAddress(from),
|
|
178
218
|
to: getAddress(to),
|
|
179
|
-
value,
|
|
180
|
-
validAfter,
|
|
181
|
-
validBefore,
|
|
182
|
-
nonce: nonce,
|
|
219
|
+
value: BigInt(value),
|
|
220
|
+
validAfter: BigInt(validAfter),
|
|
221
|
+
validBefore: BigInt(validBefore),
|
|
222
|
+
nonce: nonce as Hex,
|
|
183
223
|
},
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
signature,
|
|
184
228
|
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function signERC2612Permit(
|
|
232
|
+
account: Account,
|
|
233
|
+
{ from, value, validBefore, nonce }: ExactEvmPayloadAuthorization,
|
|
234
|
+
{ asset, network, extra }: RequestedPaymentRequirements,
|
|
235
|
+
): Promise<{ signature: Hex }> {
|
|
236
|
+
const chainId = networkToChainId(network);
|
|
237
|
+
const name = extra?.name;
|
|
238
|
+
const version = extra?.version;
|
|
239
|
+
const facilitatorAddress = extra?.facilitatorAddress;
|
|
240
|
+
if (!facilitatorAddress) {
|
|
241
|
+
throw new Error(
|
|
242
|
+
"facilitatorAddress is required in PaymentRequirements extra to pay with permit-based assets",
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
if (!name || !version) {
|
|
246
|
+
throw new Error(
|
|
247
|
+
"name and version are required in PaymentRequirements extra to pay with permit-based assets",
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
//Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline
|
|
252
|
+
const signature = await account.signTypedData({
|
|
253
|
+
types: {
|
|
254
|
+
Permit: [
|
|
255
|
+
{ name: "owner", type: "address" },
|
|
256
|
+
{ name: "spender", type: "address" },
|
|
257
|
+
{ name: "value", type: "uint256" },
|
|
258
|
+
{ name: "nonce", type: "uint256" },
|
|
259
|
+
{ name: "deadline", type: "uint256" },
|
|
260
|
+
],
|
|
261
|
+
},
|
|
262
|
+
domain: {
|
|
263
|
+
name,
|
|
264
|
+
version,
|
|
265
|
+
chainId,
|
|
266
|
+
verifyingContract: getAddress(asset),
|
|
267
|
+
},
|
|
268
|
+
primaryType: "Permit" as const,
|
|
269
|
+
message: {
|
|
270
|
+
owner: getAddress(from),
|
|
271
|
+
spender: getAddress(facilitatorAddress), // approve the facilitator
|
|
272
|
+
value: BigInt(value),
|
|
273
|
+
nonce: hexToBigInt(nonce as Hex),
|
|
274
|
+
deadline: BigInt(validBefore),
|
|
275
|
+
},
|
|
276
|
+
});
|
|
185
277
|
|
|
186
|
-
const signature = await account.signTypedData(data);
|
|
187
278
|
return {
|
|
188
279
|
signature,
|
|
189
280
|
};
|
|
@@ -194,7 +285,7 @@ async function signAuthorization(
|
|
|
194
285
|
*
|
|
195
286
|
* @returns A random 32-byte nonce as a hex string
|
|
196
287
|
*/
|
|
197
|
-
function createNonce(): Hex {
|
|
288
|
+
async function createNonce(): Promise<Hex> {
|
|
198
289
|
const cryptoObj =
|
|
199
290
|
typeof globalThis.crypto !== "undefined" &&
|
|
200
291
|
typeof globalThis.crypto.getRandomValues === "function"
|
package/src/x402/types.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ERC20TokenAmount,
|
|
3
|
-
Money,
|
|
4
|
-
PaymentMiddlewareConfig,
|
|
5
|
-
} from "x402/types";
|
|
1
|
+
import type { Money, PaymentMiddlewareConfig } from "x402/types";
|
|
6
2
|
import type { Chain } from "../chains/types.js";
|
|
7
3
|
import type { Address } from "../utils/address.js";
|
|
8
4
|
import type { Prettify } from "../utils/type-utils.js";
|
|
9
|
-
import type {
|
|
5
|
+
import type { ThirdwebX402Facilitator } from "./facilitator.js";
|
|
10
6
|
import type {
|
|
11
7
|
FacilitatorNetwork,
|
|
12
8
|
FacilitatorSettleResponse,
|
|
@@ -35,7 +31,7 @@ export type PaymentArgs = {
|
|
|
35
31
|
/** The price for accessing the resource - either a USD amount (e.g., "$0.10") or a specific token amount */
|
|
36
32
|
price: Money | ERC20TokenAmount;
|
|
37
33
|
/** The payment facilitator instance used to verify and settle payments */
|
|
38
|
-
facilitator:
|
|
34
|
+
facilitator: ThirdwebX402Facilitator;
|
|
39
35
|
/** Optional configuration for the payment middleware route */
|
|
40
36
|
routeConfig?: PaymentMiddlewareConfig;
|
|
41
37
|
};
|
|
@@ -89,3 +85,18 @@ export type VerifyPaymentResult = Prettify<
|
|
|
89
85
|
}
|
|
90
86
|
| PaymentRequiredResult
|
|
91
87
|
>;
|
|
88
|
+
|
|
89
|
+
export type SupportedSignatureType = "TransferWithAuthorization" | "Permit";
|
|
90
|
+
|
|
91
|
+
export type ERC20TokenAmount = {
|
|
92
|
+
amount: string;
|
|
93
|
+
asset: {
|
|
94
|
+
address: `0x${string}`;
|
|
95
|
+
decimals: number;
|
|
96
|
+
eip712: {
|
|
97
|
+
name: string;
|
|
98
|
+
version: string;
|
|
99
|
+
primaryType: SupportedSignatureType;
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
};
|