@bosonprotocol/core-sdk 1.47.1-alpha.0 → 1.48.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.
Files changed (49) hide show
  1. package/dist/cjs/erc20/handler.d.ts +73 -0
  2. package/dist/cjs/erc20/handler.d.ts.map +1 -1
  3. package/dist/cjs/erc20/handler.js +198 -0
  4. package/dist/cjs/erc20/handler.js.map +1 -1
  5. package/dist/cjs/erc20/mixin.d.ts +76 -1
  6. package/dist/cjs/erc20/mixin.d.ts.map +1 -1
  7. package/dist/cjs/erc20/mixin.js +67 -0
  8. package/dist/cjs/erc20/mixin.js.map +1 -1
  9. package/dist/cjs/meta-tx/handler.d.ts +2 -0
  10. package/dist/cjs/meta-tx/handler.d.ts.map +1 -1
  11. package/dist/cjs/meta-tx/handler.js +28 -19
  12. package/dist/cjs/meta-tx/handler.js.map +1 -1
  13. package/dist/cjs/meta-tx/mixin.d.ts +2 -0
  14. package/dist/cjs/meta-tx/mixin.d.ts.map +1 -1
  15. package/dist/cjs/meta-tx/mixin.js +2 -1
  16. package/dist/cjs/meta-tx/mixin.js.map +1 -1
  17. package/dist/cjs/native-meta-tx/handler.d.ts +1 -1
  18. package/dist/cjs/native-meta-tx/handler.d.ts.map +1 -1
  19. package/dist/cjs/utils/signature.d.ts +9 -0
  20. package/dist/cjs/utils/signature.d.ts.map +1 -1
  21. package/dist/cjs/utils/signature.js.map +1 -1
  22. package/dist/esm/erc20/handler.d.ts +73 -0
  23. package/dist/esm/erc20/handler.d.ts.map +1 -1
  24. package/dist/esm/erc20/handler.js +217 -0
  25. package/dist/esm/erc20/handler.js.map +1 -1
  26. package/dist/esm/erc20/mixin.d.ts +76 -1
  27. package/dist/esm/erc20/mixin.d.ts.map +1 -1
  28. package/dist/esm/erc20/mixin.js +79 -1
  29. package/dist/esm/erc20/mixin.js.map +1 -1
  30. package/dist/esm/meta-tx/handler.d.ts +2 -0
  31. package/dist/esm/meta-tx/handler.d.ts.map +1 -1
  32. package/dist/esm/meta-tx/handler.js +19 -11
  33. package/dist/esm/meta-tx/handler.js.map +1 -1
  34. package/dist/esm/meta-tx/mixin.d.ts +2 -0
  35. package/dist/esm/meta-tx/mixin.d.ts.map +1 -1
  36. package/dist/esm/meta-tx/mixin.js +2 -1
  37. package/dist/esm/meta-tx/mixin.js.map +1 -1
  38. package/dist/esm/native-meta-tx/handler.d.ts +1 -1
  39. package/dist/esm/native-meta-tx/handler.d.ts.map +1 -1
  40. package/dist/esm/utils/signature.d.ts +9 -0
  41. package/dist/esm/utils/signature.d.ts.map +1 -1
  42. package/dist/esm/utils/signature.js.map +1 -1
  43. package/package.json +3 -3
  44. package/src/erc20/handler.ts +354 -0
  45. package/src/erc20/mixin.ts +206 -1
  46. package/src/meta-tx/handler.ts +24 -11
  47. package/src/meta-tx/mixin.ts +4 -1
  48. package/src/native-meta-tx/handler.ts +1 -1
  49. package/src/utils/signature.ts +18 -6
@@ -3,8 +3,92 @@ import {
3
3
  TransactionRequest,
4
4
  TransactionResponse
5
5
  } from "@bosonprotocol/common";
6
+ import { defaultAbiCoder } from "@ethersproject/abi";
6
7
  import { BigNumber, BigNumberish } from "@ethersproject/bignumber";
8
+ import { hexlify } from "@ethersproject/bytes";
9
+ import { randomBytes } from "@ethersproject/random";
7
10
  import { erc20Iface } from "./interface";
11
+ import type { ApproveExchangeTokenBaseArgs } from "../native-meta-tx/handler";
12
+ import { alternativeNonceIface } from "../native-meta-tx/interface";
13
+ import {
14
+ prepareDataSignatureParameters,
15
+ StructuredData
16
+ } from "../utils/signature";
17
+
18
+ export type UnsignedTransferAuthorization =
19
+ | {
20
+ strategy: "ERC3009";
21
+ data: {
22
+ validAfter: BigNumberish;
23
+ validBefore: BigNumberish;
24
+ nonce: string;
25
+ };
26
+ }
27
+ | {
28
+ strategy: "EIP2612";
29
+ data: { deadline: BigNumberish };
30
+ }
31
+ | {
32
+ strategy: "Permit2";
33
+ data: { nonce: BigNumberish; deadline: BigNumberish };
34
+ };
35
+
36
+ export type TransferAuthorization = UnsignedTransferAuthorization & {
37
+ r: string;
38
+ s: string;
39
+ v: number;
40
+ signature: string;
41
+ };
42
+
43
+ const TRANSFER_STRATEGY_ID = {
44
+ ERC3009: 1,
45
+ EIP2612: 2,
46
+ Permit2: 3
47
+ } as const;
48
+
49
+ function encodeTransferAuthorizationEntry(auth: TransferAuthorization): string {
50
+ let innerData: string;
51
+ switch (auth.strategy) {
52
+ case "ERC3009":
53
+ innerData = defaultAbiCoder.encode(
54
+ ["uint256", "uint256", "bytes32", "uint8", "bytes32", "bytes32"],
55
+ [
56
+ auth.data.validAfter,
57
+ auth.data.validBefore,
58
+ auth.data.nonce,
59
+ auth.v,
60
+ auth.r,
61
+ auth.s
62
+ ]
63
+ );
64
+ break;
65
+ case "EIP2612":
66
+ innerData = defaultAbiCoder.encode(
67
+ ["uint256", "uint8", "bytes32", "bytes32"],
68
+ [auth.data.deadline, auth.v, auth.r, auth.s]
69
+ );
70
+ break;
71
+ case "Permit2":
72
+ innerData = defaultAbiCoder.encode(
73
+ ["uint256", "uint256", "bytes"],
74
+ [auth.data.nonce, auth.data.deadline, auth.signature]
75
+ );
76
+ break;
77
+ }
78
+ return defaultAbiCoder.encode(
79
+ ["uint8", "bytes"],
80
+ [TRANSFER_STRATEGY_ID[auth.strategy], innerData]
81
+ );
82
+ }
83
+
84
+ export function encodeTransferAuthorizationQueue(
85
+ auths: TransferAuthorization[]
86
+ ): string {
87
+ return defaultAbiCoder.encode(
88
+ ["bytes[]"],
89
+ [auths.map(encodeTransferAuthorizationEntry)]
90
+ );
91
+ }
8
92
 
9
93
  // Overload: returnTxInfo is true -> returns TransactionRequest
10
94
  export async function approve(args: {
@@ -130,3 +214,273 @@ export async function balanceOf(args: {
130
214
  const [balance] = erc20Iface.decodeFunctionResult("balanceOf", result);
131
215
  return String(balance);
132
216
  }
217
+
218
+ type SignReceiveWithErc3009AuthorizationArgs = ApproveExchangeTokenBaseArgs & {
219
+ tokenDomain: { name: string; version: string };
220
+ validAfter: BigNumberish;
221
+ validBefore: BigNumberish;
222
+ };
223
+
224
+ // Overload: returnTypedDataToSign is true → returns StructuredData
225
+ export async function signReceiveWithErc3009Authorization(
226
+ args: SignReceiveWithErc3009AuthorizationArgs & {
227
+ returnTypedDataToSign: true;
228
+ }
229
+ ): Promise<StructuredData>;
230
+ // Overload: returnTypedDataToSign is false or undefined → returns TransferAuthorization (ERC3009)
231
+ export async function signReceiveWithErc3009Authorization(
232
+ args: SignReceiveWithErc3009AuthorizationArgs & {
233
+ returnTypedDataToSign?: false | undefined;
234
+ }
235
+ ): Promise<TransferAuthorization & { strategy: "ERC3009" }>;
236
+ // Implementation
237
+ export async function signReceiveWithErc3009Authorization(
238
+ args: SignReceiveWithErc3009AuthorizationArgs & {
239
+ returnTypedDataToSign?: boolean;
240
+ }
241
+ ): Promise<(TransferAuthorization & { strategy: "ERC3009" }) | StructuredData> {
242
+ const nonce = hexlify(randomBytes(32));
243
+
244
+ const customSignatureType = {
245
+ EIP712Domain: [
246
+ { name: "name", type: "string" },
247
+ { name: "version", type: "string" },
248
+ { name: "chainId", type: "uint256" },
249
+ { name: "verifyingContract", type: "address" }
250
+ ],
251
+ ReceiveWithAuthorization: [
252
+ { name: "from", type: "address" },
253
+ { name: "to", type: "address" },
254
+ { name: "value", type: "uint256" },
255
+ { name: "validAfter", type: "uint256" },
256
+ { name: "validBefore", type: "uint256" },
257
+ { name: "nonce", type: "bytes32" }
258
+ ]
259
+ };
260
+
261
+ const customDomainData = {
262
+ name: args.tokenDomain.name,
263
+ version: args.tokenDomain.version,
264
+ chainId: args.chainId,
265
+ salt: undefined
266
+ };
267
+
268
+ const message = {
269
+ from: args.user,
270
+ to: args.spender,
271
+ value: args.value.toString(),
272
+ validAfter: args.validAfter.toString(),
273
+ validBefore: args.validBefore.toString(),
274
+ nonce
275
+ };
276
+
277
+ const baseParams = {
278
+ web3Lib: args.web3Lib,
279
+ chainId: args.chainId,
280
+ verifyingContractAddress: args.exchangeToken,
281
+ customSignatureType,
282
+ customDomainData,
283
+ primaryType: "ReceiveWithAuthorization",
284
+ message
285
+ };
286
+
287
+ if (args.returnTypedDataToSign) {
288
+ return prepareDataSignatureParameters({
289
+ ...baseParams,
290
+ returnTypedDataToSign: true
291
+ });
292
+ }
293
+
294
+ const sig = await prepareDataSignatureParameters({
295
+ ...baseParams,
296
+ returnTypedDataToSign: false
297
+ });
298
+
299
+ return {
300
+ ...sig,
301
+ strategy: "ERC3009",
302
+ data: {
303
+ validAfter: args.validAfter,
304
+ validBefore: args.validBefore,
305
+ nonce
306
+ }
307
+ };
308
+ }
309
+
310
+ type SignReceiveWithErc2612PermitArgs = ApproveExchangeTokenBaseArgs & {
311
+ tokenDomain: { name: string; version: string };
312
+ deadline: BigNumberish;
313
+ };
314
+
315
+ // Overload: returnTypedDataToSign is true → returns StructuredData
316
+ export async function signReceiveWithErc2612Permit(
317
+ args: SignReceiveWithErc2612PermitArgs & {
318
+ returnTypedDataToSign: true;
319
+ }
320
+ ): Promise<StructuredData>;
321
+ // Overload: returnTypedDataToSign is false or undefined → returns TransferAuthorization (EIP2612)
322
+ export async function signReceiveWithErc2612Permit(
323
+ args: SignReceiveWithErc2612PermitArgs & {
324
+ returnTypedDataToSign?: false | undefined;
325
+ }
326
+ ): Promise<TransferAuthorization & { strategy: "EIP2612" }>;
327
+ // Implementation
328
+ export async function signReceiveWithErc2612Permit(
329
+ args: SignReceiveWithErc2612PermitArgs & {
330
+ returnTypedDataToSign?: boolean;
331
+ }
332
+ ): Promise<(TransferAuthorization & { strategy: "EIP2612" }) | StructuredData> {
333
+ const nonceResult = await args.web3Lib.call({
334
+ to: args.exchangeToken,
335
+ data: alternativeNonceIface.encodeFunctionData("nonces", [args.user])
336
+ });
337
+ const [nonce] = alternativeNonceIface.decodeFunctionResult(
338
+ "nonces",
339
+ nonceResult
340
+ );
341
+
342
+ const customSignatureType = {
343
+ EIP712Domain: [
344
+ { name: "name", type: "string" },
345
+ { name: "version", type: "string" },
346
+ { name: "chainId", type: "uint256" },
347
+ { name: "verifyingContract", type: "address" }
348
+ ],
349
+ Permit: [
350
+ { name: "owner", type: "address" },
351
+ { name: "spender", type: "address" },
352
+ { name: "value", type: "uint256" },
353
+ { name: "nonce", type: "uint256" },
354
+ { name: "deadline", type: "uint256" }
355
+ ]
356
+ };
357
+
358
+ const customDomainData = {
359
+ name: args.tokenDomain.name,
360
+ version: args.tokenDomain.version,
361
+ chainId: args.chainId,
362
+ salt: undefined
363
+ };
364
+
365
+ const message = {
366
+ owner: args.user,
367
+ spender: args.spender,
368
+ value: args.value.toString(),
369
+ nonce: nonce.toString(),
370
+ deadline: args.deadline.toString()
371
+ };
372
+
373
+ const baseParams = {
374
+ web3Lib: args.web3Lib,
375
+ chainId: args.chainId,
376
+ verifyingContractAddress: args.exchangeToken,
377
+ customSignatureType,
378
+ customDomainData,
379
+ primaryType: "Permit",
380
+ message
381
+ };
382
+
383
+ if (args.returnTypedDataToSign) {
384
+ return prepareDataSignatureParameters({
385
+ ...baseParams,
386
+ returnTypedDataToSign: true
387
+ });
388
+ }
389
+
390
+ const sig = await prepareDataSignatureParameters({
391
+ ...baseParams,
392
+ returnTypedDataToSign: false
393
+ });
394
+
395
+ return {
396
+ ...sig,
397
+ strategy: "EIP2612",
398
+ data: { deadline: args.deadline }
399
+ };
400
+ }
401
+
402
+ type SignReceiveWithPermit2Args = ApproveExchangeTokenBaseArgs & {
403
+ permit2Address: string;
404
+ deadline: BigNumberish;
405
+ permit2Nonce?: BigNumberish;
406
+ };
407
+
408
+ // Overload: returnTypedDataToSign is true → returns StructuredData
409
+ export async function signReceiveWithPermit2(
410
+ args: SignReceiveWithPermit2Args & { returnTypedDataToSign: true }
411
+ ): Promise<StructuredData>;
412
+ // Overload: returnTypedDataToSign is false or undefined → returns TransferAuthorization (Permit2)
413
+ export async function signReceiveWithPermit2(
414
+ args: SignReceiveWithPermit2Args & {
415
+ returnTypedDataToSign?: false | undefined;
416
+ }
417
+ ): Promise<TransferAuthorization & { strategy: "Permit2" }>;
418
+ // Implementation
419
+ export async function signReceiveWithPermit2(
420
+ args: SignReceiveWithPermit2Args & { returnTypedDataToSign?: boolean }
421
+ ): Promise<(TransferAuthorization & { strategy: "Permit2" }) | StructuredData> {
422
+ const permit2Nonce = args.permit2Nonce ?? BigNumber.from(randomBytes(32));
423
+
424
+ const customSignatureType = {
425
+ EIP712Domain: [
426
+ { name: "name", type: "string" },
427
+ { name: "chainId", type: "uint256" },
428
+ { name: "verifyingContract", type: "address" }
429
+ ],
430
+ PermitTransferFrom: [
431
+ { name: "permitted", type: "TokenPermissions" },
432
+ { name: "spender", type: "address" },
433
+ { name: "nonce", type: "uint256" },
434
+ { name: "deadline", type: "uint256" }
435
+ ],
436
+ TokenPermissions: [
437
+ { name: "token", type: "address" },
438
+ { name: "amount", type: "uint256" }
439
+ ]
440
+ };
441
+
442
+ const customDomainData = {
443
+ name: "Permit2",
444
+ chainId: args.chainId,
445
+ version: undefined,
446
+ salt: undefined
447
+ };
448
+
449
+ const message = {
450
+ permitted: {
451
+ token: args.exchangeToken,
452
+ amount: args.value.toString()
453
+ },
454
+ spender: args.spender,
455
+ nonce: permit2Nonce.toString(),
456
+ deadline: args.deadline.toString()
457
+ };
458
+
459
+ const baseParams = {
460
+ web3Lib: args.web3Lib,
461
+ chainId: args.chainId,
462
+ verifyingContractAddress: args.permit2Address,
463
+ customSignatureType,
464
+ customDomainData,
465
+ primaryType: "PermitTransferFrom",
466
+ message
467
+ };
468
+
469
+ if (args.returnTypedDataToSign) {
470
+ return prepareDataSignatureParameters({
471
+ ...baseParams,
472
+ returnTypedDataToSign: true
473
+ });
474
+ }
475
+
476
+ const sig = await prepareDataSignatureParameters({
477
+ ...baseParams,
478
+ returnTypedDataToSign: false
479
+ });
480
+
481
+ return {
482
+ ...sig,
483
+ strategy: "Permit2",
484
+ data: { nonce: permit2Nonce, deadline: args.deadline }
485
+ };
486
+ }
@@ -3,6 +3,7 @@ import {
3
3
  TransactionResponse,
4
4
  TransactionRequest
5
5
  } from "@bosonprotocol/common";
6
+ import { BigNumberish } from "@ethersproject/bignumber";
6
7
  import { BaseCoreSDK } from "./../mixins/base-core-sdk";
7
8
  import {
8
9
  approve,
@@ -11,8 +12,13 @@ import {
11
12
  getSymbol,
12
13
  getName,
13
14
  ensureAllowance,
14
- balanceOf
15
+ balanceOf,
16
+ signReceiveWithErc3009Authorization,
17
+ signReceiveWithErc2612Permit,
18
+ signReceiveWithPermit2,
19
+ TransferAuthorization
15
20
  } from "./handler";
21
+ import { StructuredData } from "../utils/signature";
16
22
 
17
23
  export class ERC20Mixin<T extends Web3LibAdapter> extends BaseCoreSDK<T> {
18
24
  /* -------------------------------------------------------------------------- */
@@ -121,4 +127,203 @@ export class ERC20Mixin<T extends Web3LibAdapter> extends BaseCoreSDK<T> {
121
127
  ): Promise<ReturnType<typeof balanceOf>> {
122
128
  return balanceOf({ web3Lib: this._web3Lib, ...args });
123
129
  }
130
+
131
+ /**
132
+ * Signs an ERC-3009 `ReceiveWithAuthorization` payload that authorizes the
133
+ * spender (default: protocol diamond) to pull `value` units of `exchangeToken`
134
+ * from the signer. Returns a `TransferAuthorization` tagged with strategy
135
+ * `"ERC3009"`, ready to feed into `relayMetaTransaction` via
136
+ * `transferAuthorizations`.
137
+ */
138
+ // Overload: returnTypedDataToSign is true → returns StructuredData
139
+ public async signReceiveWithErc3009Authorization(
140
+ exchangeToken: string,
141
+ tokenDomain: { name: string; version: string },
142
+ value: BigNumberish,
143
+ validAfter: BigNumberish,
144
+ validBefore: BigNumberish,
145
+ overrides: Partial<{ spender: string }> & { returnTypedDataToSign: true }
146
+ ): Promise<StructuredData>;
147
+ // Overload: returnTypedDataToSign is false or undefined → returns TransferAuthorization (ERC3009)
148
+ public async signReceiveWithErc3009Authorization(
149
+ exchangeToken: string,
150
+ tokenDomain: { name: string; version: string },
151
+ value: BigNumberish,
152
+ validAfter: BigNumberish,
153
+ validBefore: BigNumberish,
154
+ overrides?: Partial<{ spender: string; returnTypedDataToSign?: false }>
155
+ ): Promise<TransferAuthorization & { strategy: "ERC3009" }>;
156
+ // Implementation
157
+ public async signReceiveWithErc3009Authorization(
158
+ exchangeToken: string,
159
+ tokenDomain: { name: string; version: string },
160
+ value: BigNumberish,
161
+ validAfter: BigNumberish,
162
+ validBefore: BigNumberish,
163
+ overrides: Partial<{
164
+ spender: string;
165
+ returnTypedDataToSign: boolean;
166
+ }> = {}
167
+ ): Promise<
168
+ (TransferAuthorization & { strategy: "ERC3009" }) | StructuredData
169
+ > {
170
+ const user = await this._web3Lib.getSignerAddress();
171
+ const baseArgs = {
172
+ web3Lib: this._web3Lib,
173
+ chainId: this._chainId,
174
+ user,
175
+ exchangeToken,
176
+ spender: overrides.spender || this._protocolDiamond,
177
+ value,
178
+ tokenDomain,
179
+ validAfter,
180
+ validBefore
181
+ };
182
+ if (overrides.returnTypedDataToSign) {
183
+ return signReceiveWithErc3009Authorization({
184
+ ...baseArgs,
185
+ returnTypedDataToSign: true
186
+ });
187
+ }
188
+ return signReceiveWithErc3009Authorization({
189
+ ...baseArgs,
190
+ returnTypedDataToSign: false
191
+ });
192
+ }
193
+
194
+ /**
195
+ * Signs an EIP-2612 `Permit` payload that authorizes the spender (default:
196
+ * protocol diamond) to pull `value` units of `exchangeToken` from the signer
197
+ * up to `deadline`. Returns a `TransferAuthorization` tagged with strategy
198
+ * `"EIP2612"`, ready to feed into `relayMetaTransaction` via
199
+ * `transferAuthorizations`.
200
+ */
201
+ // Overload: returnTypedDataToSign is true → returns StructuredData
202
+ public async signReceiveWithErc2612Permit(
203
+ exchangeToken: string,
204
+ tokenDomain: { name: string; version: string },
205
+ value: BigNumberish,
206
+ deadline: BigNumberish,
207
+ overrides: Partial<{ spender: string }> & { returnTypedDataToSign: true }
208
+ ): Promise<StructuredData>;
209
+ // Overload: returnTypedDataToSign is false or undefined → returns TransferAuthorization (EIP2612)
210
+ public async signReceiveWithErc2612Permit(
211
+ exchangeToken: string,
212
+ tokenDomain: { name: string; version: string },
213
+ value: BigNumberish,
214
+ deadline: BigNumberish,
215
+ overrides?: Partial<{ spender: string; returnTypedDataToSign?: false }>
216
+ ): Promise<TransferAuthorization & { strategy: "EIP2612" }>;
217
+ // Implementation
218
+ public async signReceiveWithErc2612Permit(
219
+ exchangeToken: string,
220
+ tokenDomain: { name: string; version: string },
221
+ value: BigNumberish,
222
+ deadline: BigNumberish,
223
+ overrides: Partial<{
224
+ spender: string;
225
+ returnTypedDataToSign: boolean;
226
+ }> = {}
227
+ ): Promise<
228
+ (TransferAuthorization & { strategy: "EIP2612" }) | StructuredData
229
+ > {
230
+ const user = await this._web3Lib.getSignerAddress();
231
+ const baseArgs = {
232
+ web3Lib: this._web3Lib,
233
+ chainId: this._chainId,
234
+ user,
235
+ exchangeToken,
236
+ spender: overrides.spender || this._protocolDiamond,
237
+ value,
238
+ tokenDomain,
239
+ deadline
240
+ };
241
+ if (overrides.returnTypedDataToSign) {
242
+ return signReceiveWithErc2612Permit({
243
+ ...baseArgs,
244
+ returnTypedDataToSign: true
245
+ });
246
+ }
247
+ return signReceiveWithErc2612Permit({
248
+ ...baseArgs,
249
+ returnTypedDataToSign: false
250
+ });
251
+ }
252
+
253
+ /**
254
+ * Signs a Uniswap Permit2 `PermitTransferFrom` payload authorizing the
255
+ * spender (default: protocol diamond) to pull `value` units of
256
+ * `exchangeToken` from the signer up to `deadline`. The Permit2 contract
257
+ * address defaults to `contracts.permit2` from SDK config and can be
258
+ * overridden via `overrides.permit2Address`. If `overrides.permit2Nonce`
259
+ * is omitted, a random uint256 is generated. Returns a `TransferAuthorization`
260
+ * tagged with strategy `"Permit2"`, ready to feed into `relayMetaTransaction`
261
+ * via `transferAuthorizations`.
262
+ */
263
+ // Overload: returnTypedDataToSign is true → returns StructuredData
264
+ public async signReceiveWithPermit2(
265
+ exchangeToken: string,
266
+ value: BigNumberish,
267
+ deadline: BigNumberish,
268
+ overrides: Partial<{
269
+ spender: string;
270
+ permit2Address: string;
271
+ permit2Nonce: BigNumberish;
272
+ }> & { returnTypedDataToSign: true }
273
+ ): Promise<StructuredData>;
274
+ // Overload: returnTypedDataToSign is false or undefined → returns TransferAuthorization (Permit2)
275
+ public async signReceiveWithPermit2(
276
+ exchangeToken: string,
277
+ value: BigNumberish,
278
+ deadline: BigNumberish,
279
+ overrides?: Partial<{
280
+ spender: string;
281
+ permit2Address: string;
282
+ permit2Nonce: BigNumberish;
283
+ returnTypedDataToSign?: false;
284
+ }>
285
+ ): Promise<TransferAuthorization & { strategy: "Permit2" }>;
286
+ // Implementation
287
+ public async signReceiveWithPermit2(
288
+ exchangeToken: string,
289
+ value: BigNumberish,
290
+ deadline: BigNumberish,
291
+ overrides: Partial<{
292
+ spender: string;
293
+ permit2Address: string;
294
+ permit2Nonce: BigNumberish;
295
+ returnTypedDataToSign: boolean;
296
+ }> = {}
297
+ ): Promise<
298
+ (TransferAuthorization & { strategy: "Permit2" }) | StructuredData
299
+ > {
300
+ const user = await this._web3Lib.getSignerAddress();
301
+ const permit2Address = overrides.permit2Address || this._contracts?.permit2;
302
+ if (!permit2Address) {
303
+ throw new Error(
304
+ "Permit2 contract address not configured. Provide overrides.permit2Address or initialize CoreSDK with contracts.permit2."
305
+ );
306
+ }
307
+ const baseArgs = {
308
+ web3Lib: this._web3Lib,
309
+ chainId: this._chainId,
310
+ user,
311
+ exchangeToken,
312
+ spender: overrides.spender || this._protocolDiamond,
313
+ value,
314
+ permit2Address,
315
+ deadline,
316
+ permit2Nonce: overrides.permit2Nonce
317
+ };
318
+ if (overrides.returnTypedDataToSign) {
319
+ return signReceiveWithPermit2({
320
+ ...baseArgs,
321
+ returnTypedDataToSign: true
322
+ });
323
+ }
324
+ return signReceiveWithPermit2({
325
+ ...baseArgs,
326
+ returnTypedDataToSign: false
327
+ });
328
+ }
124
329
  }
@@ -61,6 +61,10 @@ import {
61
61
  import { keccak256 } from "@ethersproject/keccak256";
62
62
  import { id } from "@ethersproject/hash";
63
63
  import { defaultAbiCoder } from "@ethersproject/abi";
64
+ import {
65
+ TransferAuthorization,
66
+ encodeTransferAuthorizationQueue
67
+ } from "../erc20/handler";
64
68
  import { ERC20ForwardRequest } from "../forwarder/biconomy-interface";
65
69
  import { getNonce, verifyEIP712 } from "../forwarder/handler";
66
70
  import { MockForwardRequest } from "../forwarder/mock-interface";
@@ -2018,6 +2022,7 @@ export async function relayMetaTransaction(args: {
2018
2022
  sigR: BytesLike;
2019
2023
  sigS: BytesLike;
2020
2024
  sigV: BigNumberish;
2025
+ transferAuthorizations?: TransferAuthorization[];
2021
2026
  };
2022
2027
  };
2023
2028
  }): Promise<TransactionResponse> {
@@ -2029,19 +2034,27 @@ export async function relayMetaTransaction(args: {
2029
2034
  metaTx.config.apiId
2030
2035
  );
2031
2036
 
2037
+ const baseParams: unknown[] = [
2038
+ metaTx.params.userAddress,
2039
+ metaTx.params.functionName,
2040
+ metaTx.params.functionSignature,
2041
+ metaTx.params.nonce,
2042
+ rebuildSignature({
2043
+ r: metaTx.params.sigR.toString(),
2044
+ s: metaTx.params.sigS.toString(),
2045
+ v: Number(metaTx.params.sigV)
2046
+ })
2047
+ ];
2048
+ const params = metaTx.params.transferAuthorizations?.length
2049
+ ? [
2050
+ ...baseParams,
2051
+ encodeTransferAuthorizationQueue(metaTx.params.transferAuthorizations)
2052
+ ]
2053
+ : baseParams;
2054
+
2032
2055
  const relayTxResponse = await biconomy.relayTransaction({
2033
2056
  to: contractAddress,
2034
- params: [
2035
- metaTx.params.userAddress,
2036
- metaTx.params.functionName,
2037
- metaTx.params.functionSignature,
2038
- metaTx.params.nonce,
2039
- rebuildSignature({
2040
- r: metaTx.params.sigR.toString(),
2041
- s: metaTx.params.sigS.toString(),
2042
- v: Number(metaTx.params.sigV)
2043
- })
2044
- ],
2057
+ params,
2045
2058
  from: metaTx.params.userAddress
2046
2059
  });
2047
2060
 
@@ -14,6 +14,7 @@ import { accounts } from "..";
14
14
  import { AccountsMixin } from "../accounts/mixin";
15
15
  import { SellerFieldsFragment } from "../subgraph";
16
16
  import { SignedMetaTx, UnsignedMetaTx } from "./handler";
17
+ import { TransferAuthorization } from "../erc20/handler";
17
18
  export class MetaTxMixin<T extends Web3LibAdapter> extends BaseCoreSDK<T> {
18
19
  /* -------------------------------------------------------------------------- */
19
20
  /* Meta Tx related methods */
@@ -1672,6 +1673,7 @@ export class MetaTxMixin<T extends Web3LibAdapter> extends BaseCoreSDK<T> {
1672
1673
  sigR: BytesLike;
1673
1674
  sigS: BytesLike;
1674
1675
  sigV: BigNumberish;
1676
+ transferAuthorizations?: TransferAuthorization[];
1675
1677
  },
1676
1678
  overrides: Partial<{
1677
1679
  userAddress: string;
@@ -1701,7 +1703,8 @@ export class MetaTxMixin<T extends Web3LibAdapter> extends BaseCoreSDK<T> {
1701
1703
  nonce: metaTxParams.nonce,
1702
1704
  sigR: metaTxParams.sigR,
1703
1705
  sigS: metaTxParams.sigS,
1704
- sigV: metaTxParams.sigV
1706
+ sigV: metaTxParams.sigV,
1707
+ transferAuthorizations: metaTxParams.transferAuthorizations
1705
1708
  }
1706
1709
  }
1707
1710
  });
@@ -128,7 +128,7 @@ export async function signNativeMetaTx(
128
128
  };
129
129
  }
130
130
 
131
- type ApproveExchangeTokenBaseArgs = {
131
+ export type ApproveExchangeTokenBaseArgs = {
132
132
  web3Lib: Web3LibAdapter;
133
133
  chainId: number;
134
134
  user: string;