@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.
- package/dist/cjs/erc20/handler.d.ts +73 -0
- package/dist/cjs/erc20/handler.d.ts.map +1 -1
- package/dist/cjs/erc20/handler.js +198 -0
- package/dist/cjs/erc20/handler.js.map +1 -1
- package/dist/cjs/erc20/mixin.d.ts +76 -1
- package/dist/cjs/erc20/mixin.d.ts.map +1 -1
- package/dist/cjs/erc20/mixin.js +67 -0
- package/dist/cjs/erc20/mixin.js.map +1 -1
- package/dist/cjs/meta-tx/handler.d.ts +2 -0
- package/dist/cjs/meta-tx/handler.d.ts.map +1 -1
- package/dist/cjs/meta-tx/handler.js +28 -19
- package/dist/cjs/meta-tx/handler.js.map +1 -1
- package/dist/cjs/meta-tx/mixin.d.ts +2 -0
- package/dist/cjs/meta-tx/mixin.d.ts.map +1 -1
- package/dist/cjs/meta-tx/mixin.js +2 -1
- package/dist/cjs/meta-tx/mixin.js.map +1 -1
- package/dist/cjs/native-meta-tx/handler.d.ts +1 -1
- package/dist/cjs/native-meta-tx/handler.d.ts.map +1 -1
- package/dist/cjs/utils/signature.d.ts +9 -0
- package/dist/cjs/utils/signature.d.ts.map +1 -1
- package/dist/cjs/utils/signature.js.map +1 -1
- package/dist/esm/erc20/handler.d.ts +73 -0
- package/dist/esm/erc20/handler.d.ts.map +1 -1
- package/dist/esm/erc20/handler.js +217 -0
- package/dist/esm/erc20/handler.js.map +1 -1
- package/dist/esm/erc20/mixin.d.ts +76 -1
- package/dist/esm/erc20/mixin.d.ts.map +1 -1
- package/dist/esm/erc20/mixin.js +79 -1
- package/dist/esm/erc20/mixin.js.map +1 -1
- package/dist/esm/meta-tx/handler.d.ts +2 -0
- package/dist/esm/meta-tx/handler.d.ts.map +1 -1
- package/dist/esm/meta-tx/handler.js +19 -11
- package/dist/esm/meta-tx/handler.js.map +1 -1
- package/dist/esm/meta-tx/mixin.d.ts +2 -0
- package/dist/esm/meta-tx/mixin.d.ts.map +1 -1
- package/dist/esm/meta-tx/mixin.js +2 -1
- package/dist/esm/meta-tx/mixin.js.map +1 -1
- package/dist/esm/native-meta-tx/handler.d.ts +1 -1
- package/dist/esm/native-meta-tx/handler.d.ts.map +1 -1
- package/dist/esm/utils/signature.d.ts +9 -0
- package/dist/esm/utils/signature.d.ts.map +1 -1
- package/dist/esm/utils/signature.js.map +1 -1
- package/package.json +3 -3
- package/src/erc20/handler.ts +354 -0
- package/src/erc20/mixin.ts +206 -1
- package/src/meta-tx/handler.ts +24 -11
- package/src/meta-tx/mixin.ts +4 -1
- package/src/native-meta-tx/handler.ts +1 -1
- package/src/utils/signature.ts +18 -6
package/src/erc20/handler.ts
CHANGED
|
@@ -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
|
+
}
|
package/src/erc20/mixin.ts
CHANGED
|
@@ -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
|
}
|
package/src/meta-tx/handler.ts
CHANGED
|
@@ -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
|
|
package/src/meta-tx/mixin.ts
CHANGED
|
@@ -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
|
});
|