Skip to content

Commit 72bc847

Browse files
committed
Handle dynamic contract default extensions
1 parent 6911102 commit 72bc847

File tree

4 files changed

+117
-24
lines changed

4 files changed

+117
-24
lines changed

packages/thirdweb/src/contract/deployment/utils/bootstrap.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,11 @@ export async function getOrDeployInfraForPublishedContract(
142142
version,
143143
});
144144
}
145-
return { cloneFactoryContract, implementationContract };
145+
146+
return {
147+
cloneFactoryContract,
148+
implementationContract,
149+
};
146150
}
147151

148152
/**

packages/thirdweb/src/extensions/prebuilts/deploy-marketplace.ts

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
import type {
2-
Abi,
3-
AbiFunction,
4-
AbiParametersToPrimitiveTypes,
5-
Address,
6-
} from "abitype";
7-
import { toFunctionSelector, toFunctionSignature } from "viem";
1+
import type { AbiParametersToPrimitiveTypes, Address } from "abitype";
82
import type { ThirdwebClient } from "../../client/client.js";
93
import { resolveContractAbi } from "../../contract/actions/resolve-abi.js";
104
import type { ThirdwebContract } from "../../contract/contract.js";
@@ -19,6 +13,7 @@ import { getRoyaltyEngineV1ByChainId } from "../../utils/royalty-engine.js";
1913
import type { Prettify } from "../../utils/type-utils.js";
2014
import type { ClientAndChainAndAccount } from "../../utils/types.js";
2115
import { initialize as initMarketplace } from "./__generated__/Marketplace/write/initialize.js";
16+
import { generateExtensionFunctionsFromAbi } from "./get-required-transactions.js";
2217

2318
export type MarketplaceContractParams = {
2419
name: string;
@@ -199,22 +194,6 @@ async function getInitializeTransaction(options: {
199194
});
200195
}
201196

202-
// helperFns
203-
204-
function generateExtensionFunctionsFromAbi(abi: Abi): Array<{
205-
functionSelector: string;
206-
functionSignature: string;
207-
}> {
208-
const functions = abi.filter(
209-
(item) => item.type === "function" && !item.name.startsWith("_"),
210-
) as AbiFunction[];
211-
212-
return functions.map((fn) => ({
213-
functionSelector: toFunctionSelector(fn),
214-
functionSignature: toFunctionSignature(fn),
215-
}));
216-
}
217-
218197
// let's just ... put this down here
219198
type MarketplaceConstructorParams = AbiParametersToPrimitiveTypes<
220199
[

packages/thirdweb/src/extensions/prebuilts/deploy-published.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,29 @@ export async function deployContractfromDeployMetadata(
204204
import("../../contract/deployment/deploy-via-autofactory.js"),
205205
import("../../contract/deployment/utils/bootstrap.js"),
206206
]);
207+
208+
if (
209+
deployMetadata.routerType === "dynamic" &&
210+
deployMetadata.defaultExtensions
211+
) {
212+
for (const e of deployMetadata.defaultExtensions) {
213+
await getOrDeployInfraForPublishedContract({
214+
chain,
215+
client,
216+
account,
217+
contractId: e.extensionName,
218+
version: e.extensionVersion || "latest",
219+
publisher: e.publisherAddress,
220+
constructorParams:
221+
await getAllDefaultConstructorParamsForImplementation({
222+
chain,
223+
client,
224+
contractId: e.extensionName,
225+
}),
226+
});
227+
}
228+
}
229+
207230
const { cloneFactoryContract, implementationContract } =
208231
await getOrDeployInfraForPublishedContract({
209232
chain,
@@ -216,6 +239,7 @@ export async function deployContractfromDeployMetadata(
216239
chain,
217240
client,
218241
contractId: deployMetadata.name,
242+
defaultExtensions: deployMetadata.defaultExtensions,
219243
})),
220244
publisher: deployMetadata.publisher,
221245
version: deployMetadata.version,

packages/thirdweb/src/extensions/prebuilts/get-required-transactions.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import type { Abi, AbiFunction } from "abitype";
2+
import { toFunctionSelector, toFunctionSignature } from "viem";
13
import type { Chain } from "../../chains/types.js";
24
import type { ThirdwebClient } from "../../client/client.js";
5+
import { resolveContractAbi } from "../../contract/actions/resolve-abi.js";
36
import { getDeployedCreate2Factory } from "../../contract/deployment/utils/create-2-factory.js";
47
import { getDeployedInfraContract } from "../../contract/deployment/utils/infra.js";
58
import { getDeployedInfraContractFromMetadata } from "../../contract/deployment/utils/infra.js";
@@ -19,6 +22,15 @@ type DeployTransactionType =
1922
| "extension"
2023
| "proxy";
2124

25+
/**
26+
* @internal
27+
*/
28+
export type DynamicContractExtension = {
29+
extensionName: string;
30+
extensionVersion: string;
31+
publisherAddress: string;
32+
};
33+
2234
/**
2335
* @internal
2436
*/
@@ -226,6 +238,7 @@ export async function getAllDefaultConstructorParamsForImplementation(args: {
226238
chain: Chain;
227239
client: ThirdwebClient;
228240
contractId: string;
241+
defaultExtensions?: DynamicContractExtension[];
229242
}) {
230243
const { chain, client } = args;
231244
const isZkSync = await isZkSyncChain(chain);
@@ -251,8 +264,81 @@ export async function getAllDefaultConstructorParamsForImplementation(args: {
251264
contractId: "WETH9",
252265
}),
253266
]);
267+
268+
const defaultExtensionInput = args.defaultExtensions
269+
? await generateExtensionInput({
270+
defaultExtensions: args.defaultExtensions,
271+
chain,
272+
client,
273+
forwarder,
274+
nativeTokenWrapper: weth,
275+
})
276+
: [];
277+
254278
return {
255279
trustedForwarder: forwarder,
256280
nativeTokenWrapper: weth,
281+
extensions: defaultExtensionInput,
257282
};
258283
}
284+
285+
async function generateExtensionInput(args: {
286+
defaultExtensions: DynamicContractExtension[];
287+
chain: Chain;
288+
client: ThirdwebClient;
289+
forwarder: string;
290+
nativeTokenWrapper: string;
291+
}) {
292+
const { defaultExtensions, chain, client, forwarder, nativeTokenWrapper } =
293+
args;
294+
295+
const deployedExtensions = await Promise.all(
296+
defaultExtensions.map((e) =>
297+
getDeployedInfraContract({
298+
chain,
299+
client,
300+
contractId: e.extensionName,
301+
publisher: e.publisherAddress,
302+
version: e.extensionVersion || "latest",
303+
constructorParams: { forwarder, nativeTokenWrapper },
304+
}).then((c) => ({
305+
name: e.extensionName,
306+
metadataURI: "",
307+
implementation: c,
308+
})),
309+
),
310+
);
311+
312+
const extensionInput = await Promise.all(
313+
deployedExtensions.map(async (e) => {
314+
if (!e.implementation) {
315+
throw new Error("Extension not deployed");
316+
}
317+
return resolveContractAbi(e.implementation)
318+
.then(generateExtensionFunctionsFromAbi)
319+
.then((c) => ({
320+
metadata: {
321+
...e,
322+
implementation: e.implementation?.address,
323+
},
324+
functions: c,
325+
}));
326+
}),
327+
);
328+
329+
return extensionInput;
330+
}
331+
332+
export function generateExtensionFunctionsFromAbi(abi: Abi): Array<{
333+
functionSelector: string;
334+
functionSignature: string;
335+
}> {
336+
const functions = abi.filter(
337+
(item) => item.type === "function" && !item.name.startsWith("_"),
338+
) as AbiFunction[];
339+
340+
return functions.map((fn) => ({
341+
functionSelector: toFunctionSelector(fn),
342+
functionSignature: toFunctionSignature(fn),
343+
}));
344+
}

0 commit comments

Comments
 (0)