Skip to content

Commit 1dc5d59

Browse files
authored
feat: Support v5 SDK format for signatureGenerate endpoints (#555)
* wip * feat: Support v5 format for signatureGenerate endpoints * fix fastify error * Support ERC721/1155 signatureGenerate endpoints * Support smart account * remove unused args
1 parent f5a269a commit 1dc5d59

File tree

8 files changed

+554
-80
lines changed

8 files changed

+554
-80
lines changed

src/server/routes/contract/extensions/erc1155/read/signatureGenerate.ts

Lines changed: 167 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,86 @@
11
import { Static, Type } from "@sinclair/typebox";
22
import { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
4-
import { getContract } from "../../../../../../utils/cache/getContract";
4+
import { Address, Hex, defineChain, getContract } from "thirdweb";
5+
import { NFTInput } from "thirdweb/dist/types/utils/nft/parseNft";
6+
import { generateMintSignature } from "thirdweb/extensions/erc1155";
7+
import { getAccount } from "../../../../../../utils/account";
8+
import { getContract as getContractV4 } from "../../../../../../utils/cache/getContract";
9+
import { thirdwebClient } from "../../../../../../utils/sdk";
10+
import { createCustomError } from "../../../../../middleware/error";
11+
import { thirdwebSdkVersionSchema } from "../../../../../schemas/httpHeaders/thirdwebSdkVersion";
512
import {
613
ercNFTResponseType,
14+
nftInputSchema,
715
signature1155InputSchema,
816
signature1155OutputSchema,
917
} from "../../../../../schemas/nft";
1018
import {
11-
erc721ContractParamSchema,
19+
erc1155ContractParamSchema,
1220
standardResponseSchema,
1321
} from "../../../../../schemas/sharedApiSchemas";
1422
import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet";
1523
import { getChainIdFromChain } from "../../../../../utils/chain";
1624
import { checkAndReturnNFTSignaturePayload } from "../../../../../utils/validator";
1725

18-
// INPUTS
19-
const requestSchema = erc721ContractParamSchema;
20-
const requestBodySchema = signature1155InputSchema;
26+
// v4 sdk
27+
const requestBodySchemaV4 = signature1155InputSchema;
28+
const responseSchemaV4 = Type.Object({
29+
payload: signature1155OutputSchema,
30+
signature: Type.String(),
31+
});
2132

22-
// OUTPUT
23-
const responseSchema = Type.Object({
24-
result: Type.Object({
25-
payload: signature1155OutputSchema,
26-
signature: Type.String(),
33+
// v5 sdk
34+
const requestBodySchemaV5 = Type.Intersect([
35+
Type.Object({
36+
contractType: Type.Optional(
37+
Type.Union([
38+
Type.Literal("TokenERC1155"),
39+
Type.Literal("SignatureMintERC1155"),
40+
]),
41+
),
42+
to: Type.String(),
43+
quantity: Type.String(),
44+
royaltyRecipient: Type.Optional(Type.String()),
45+
royaltyBps: Type.Optional(Type.Number()),
46+
primarySaleRecipient: Type.Optional(Type.String()),
47+
pricePerToken: Type.Optional(Type.String()),
48+
pricePerTokenWei: Type.Optional(Type.String()),
49+
currency: Type.Optional(Type.String()),
50+
validityStartTimestamp: Type.Integer(),
51+
validityEndTimestamp: Type.Optional(Type.Integer()),
52+
uid: Type.Optional(Type.String()),
2753
}),
54+
Type.Union([
55+
Type.Object({ metadata: Type.Union([nftInputSchema, Type.String()]) }),
56+
Type.Object({ tokenId: Type.String() }),
57+
]),
58+
]);
59+
const responseSchemaV5 = Type.Object({
60+
payload: Type.Object({
61+
to: Type.String(),
62+
royaltyRecipient: Type.String(),
63+
royaltyBps: Type.String(),
64+
primarySaleRecipient: Type.String(),
65+
tokenId: Type.String(),
66+
uri: Type.String(),
67+
quantity: Type.String(),
68+
pricePerToken: Type.String(),
69+
currency: Type.String(),
70+
validityStartTimestamp: Type.Integer(),
71+
validityEndTimestamp: Type.Integer(),
72+
uid: Type.String(),
73+
}),
74+
signature: Type.String(),
75+
});
76+
77+
const requestSchema = erc1155ContractParamSchema;
78+
const requestBodySchema = Type.Union([
79+
requestBodySchemaV4,
80+
requestBodySchemaV5,
81+
]);
82+
const responseSchema = Type.Object({
83+
result: Type.Union([responseSchemaV4, responseSchemaV5]),
2884
});
2985

3086
responseSchema.example = {
@@ -43,38 +99,129 @@ export async function erc1155SignatureGenerate(fastify: FastifyInstance) {
4399
schema: {
44100
summary: "Generate signature",
45101
description:
46-
"Generate a signature granting access for another wallet to mint tokens from this ERC-721 contract. This method is typically called by the token contract owner.",
102+
"Generate a signature granting access for another wallet to mint tokens from this ERC-1155 contract. This method is typically called by the token contract owner.",
47103
tags: ["ERC1155"],
48104
operationId: "signatureGenerate",
49105
params: requestSchema,
50106
body: requestBodySchema,
51-
headers: walletWithAAHeaderSchema,
107+
headers: {
108+
...walletWithAAHeaderSchema.properties,
109+
...thirdwebSdkVersionSchema.properties,
110+
},
52111
response: {
53112
...standardResponseSchema,
54113
[StatusCodes.OK]: responseSchema,
55114
},
56115
},
57116
handler: async (request, reply) => {
58117
const { chain, contractAddress } = request.params;
118+
const {
119+
"x-backend-wallet-address": walletAddress,
120+
"x-account-address": accountAddress,
121+
} = request.headers as Static<typeof walletWithAAHeaderSchema>;
122+
const { "x-thirdweb-sdk-version": sdkVersion } =
123+
request.headers as Static<typeof thirdwebSdkVersionSchema>;
124+
125+
const chainId = await getChainIdFromChain(chain);
126+
127+
// Use v5 SDK if "x-thirdweb-sdk-version" header is set.
128+
if (sdkVersion === "5") {
129+
const args = request.body as Static<typeof requestBodySchemaV5>;
130+
const {
131+
contractType,
132+
to,
133+
quantity,
134+
royaltyRecipient,
135+
royaltyBps,
136+
primarySaleRecipient,
137+
pricePerToken,
138+
pricePerTokenWei,
139+
currency,
140+
validityStartTimestamp,
141+
validityEndTimestamp,
142+
uid,
143+
} = args;
144+
145+
let nftInput: { metadata: NFTInput | string } | { tokenId: bigint };
146+
if ("metadata" in args) {
147+
nftInput = { metadata: args.metadata };
148+
} else if ("tokenId" in args) {
149+
nftInput = { tokenId: BigInt(args.tokenId) };
150+
} else {
151+
throw createCustomError(
152+
`Missing "metadata" or "tokenId".`,
153+
StatusCodes.BAD_REQUEST,
154+
"MISSING_PARAMETERS",
155+
);
156+
}
157+
158+
const contract = getContract({
159+
client: thirdwebClient,
160+
chain: defineChain(chainId),
161+
address: contractAddress,
162+
});
163+
const account = await getAccount({
164+
chainId,
165+
from: walletAddress as Address,
166+
accountAddress: accountAddress as Address,
167+
});
168+
169+
const { payload, signature } = await generateMintSignature({
170+
contract,
171+
account,
172+
contractType,
173+
mintRequest: {
174+
to,
175+
quantity: BigInt(quantity),
176+
royaltyRecipient,
177+
royaltyBps,
178+
primarySaleRecipient,
179+
pricePerToken,
180+
pricePerTokenWei: pricePerTokenWei
181+
? BigInt(pricePerTokenWei)
182+
: undefined,
183+
currency,
184+
validityStartTimestamp: new Date(validityStartTimestamp * 1000),
185+
validityEndTimestamp: validityEndTimestamp
186+
? new Date(validityEndTimestamp * 1000)
187+
: undefined,
188+
uid: uid as Hex | undefined,
189+
...nftInput,
190+
},
191+
});
192+
193+
return reply.status(StatusCodes.OK).send({
194+
result: {
195+
payload: {
196+
...payload,
197+
royaltyBps: payload.royaltyBps.toString(),
198+
tokenId: payload.tokenId.toString(),
199+
quantity: payload.quantity.toString(),
200+
pricePerToken: payload.pricePerToken.toString(),
201+
validityStartTimestamp: Number(payload.validityStartTimestamp),
202+
validityEndTimestamp: Number(payload.validityEndTimestamp),
203+
},
204+
signature,
205+
},
206+
});
207+
}
208+
209+
// Use v4 SDK.
59210
const {
60211
to,
61212
currencyAddress,
62213
metadata,
63214
mintEndTime,
64215
mintStartTime,
65-
price,
216+
price = "0",
66217
primarySaleRecipient,
67218
quantity,
68219
royaltyBps,
69220
royaltyRecipient,
70221
uid,
71-
} = request.body;
72-
const {
73-
"x-backend-wallet-address": walletAddress,
74-
"x-account-address": accountAddress,
75-
} = request.headers as Static<typeof walletWithAAHeaderSchema>;
76-
const chainId = await getChainIdFromChain(chain);
77-
const contract = await getContract({
222+
} = request.body as Static<typeof requestBodySchemaV4>;
223+
224+
const contract = await getContractV4({
78225
chainId,
79226
contractAddress,
80227
walletAddress,

0 commit comments

Comments
 (0)