Skip to content

Commit

Permalink
[SDK] Fix deploy transaction listener for all deploy types `sdk.deplo…
Browse files Browse the repository at this point in the history
…yer.addDeployListener()` (#494)
  • Loading branch information
joaquim-verges committed Jan 14, 2023
1 parent 68c8e3c commit bff433e
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 50 deletions.
5 changes: 5 additions & 0 deletions .changeset/three-mails-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@thirdweb-dev/sdk": patch
---

Fix deploy transaction listener for all deploy types `sdk.deployer.addDeployListener()`
45 changes: 38 additions & 7 deletions packages/sdk/src/evm/core/classes/contract-deployer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
} from "../../contracts";
import { FactoryDeploymentSchema } from "../../schema/contracts/custom";
import { SDKOptions } from "../../schema/sdk-options";
import { DeployEvent, DeployEvents } from "../../types";
import {
MarketplaceContractDeployMetadata,
MultiwrapContractDeployMetadata,
Expand All @@ -39,7 +40,6 @@ import {
PrebuiltContractType,
} from "../types";
import { ContractFactory } from "./factory";
import { FactoryEvents } from "./factory-events";
import { ContractRegistry } from "./registry";
import { RPCConnectionHandler } from "./rpc-connection-handler";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
Expand All @@ -50,6 +50,7 @@ import {
ContractInterface,
ethers,
} from "ethers";
import { EventEmitter } from "eventemitter3";
import invariant from "tiny-invariant";
import { z } from "zod";

Expand All @@ -68,8 +69,8 @@ export class ContractDeployer extends RPCConnectionHandler {
* should never be accessed directly, use {@link ContractDeployer.getRegistry} instead
*/
private _registry: Promise<ContractRegistry> | undefined;
public events: FactoryEvents | undefined;
private storage: ThirdwebStorage;
private events: EventEmitter<DeployEvents>;

constructor(
network: NetworkOrSignerOrProvider,
Expand All @@ -78,7 +79,7 @@ export class ContractDeployer extends RPCConnectionHandler {
) {
super(network, options);
this.storage = storage;

this.events = new EventEmitter();
// Initialize factory and registry (we don't need to make these calls async)
this.getFactory();
this.getRegistry();
Expand Down Expand Up @@ -427,7 +428,12 @@ export class ContractDeployer extends RPCConnectionHandler {
} catch (e) {
parsedVersion = undefined;
}
return await factory.deploy(contractType, parsedMetadata, parsedVersion);
return await factory.deploy(
contractType,
parsedMetadata,
this.events,
parsedVersion,
);
}

//
Expand Down Expand Up @@ -522,6 +528,7 @@ export class ContractDeployer extends RPCConnectionHandler {
implementationAbi,
initializerFunction,
initializerArgs,
this.events,
);
}

Expand Down Expand Up @@ -602,8 +609,6 @@ export class ContractDeployer extends RPCConnectionHandler {
this.storage,
this.options,
);
this.events = new FactoryEvents(factory);

return factory;
}));
}
Expand Down Expand Up @@ -801,7 +806,33 @@ export class ContractDeployer extends RPCConnectionHandler {
.connect(signer)
.deploy(...constructorParams);
const deployedContract = await deployer.deployed();
// TODO parse transaction receipt
this.events.emit("contractDeployed", {
contractAddress: deployedContract.address,
transactionHash: deployedContract.deployTransaction.hash,
});
return deployedContract.address;
}

/**
* Listen to all deploy transactions from this deployer
* @param listener the listener to add
*/
public addDeployListener(listener: (event: DeployEvent) => void) {
this.events.on("contractDeployed", listener);
}

/**
* Remove a deploy listener
* @param listener the listener to remove
*/
public removeDeployListener(listener: (event: DeployEvent) => void) {
this.events.off("contractDeployed", listener);
}

/**
* Remove all deploy listeners
*/
public removeAllDeployListeners() {
this.events.removeAllListeners("contractDeployed");
}
}
38 changes: 0 additions & 38 deletions packages/sdk/src/evm/core/classes/factory-events.ts

This file was deleted.

20 changes: 18 additions & 2 deletions packages/sdk/src/evm/core/classes/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
VoteInitializer,
} from "../../contracts";
import { SDKOptions } from "../../schema/sdk-options";
import { DeployEvents } from "../../types";
import {
DeploySchemaForPrebuiltContractType,
NetworkOrSignerOrProvider,
Expand All @@ -36,6 +37,7 @@ import {
ContractInterface,
ethers,
} from "ethers";
import { EventEmitter } from "eventemitter3";
import { z } from "zod";

/**
Expand Down Expand Up @@ -75,6 +77,7 @@ export class ContractFactory extends ContractWrapper<TWFactory> {
contractMetadata: z.input<
DeploySchemaForPrebuiltContractType<TContractType>
>,
eventEmitter: EventEmitter<DeployEvents>,
version?: number,
): Promise<string> {
const contract = PREBUILT_CONTRACTS_MAP[contractType];
Expand Down Expand Up @@ -122,7 +125,13 @@ export class ContractFactory extends ContractWrapper<TWFactory> {
throw new Error("No ProxyDeployed event found");
}

return events[0].args.proxy;
const contractAddress = events[0].args.proxy;
eventEmitter.emit("contractDeployed", {
contractAddress,
transactionHash: receipt.transactionHash,
});

return contractAddress;
}

// TODO once IContractFactory is implemented, this can be probably be moved to its own class
Expand All @@ -131,6 +140,7 @@ export class ContractFactory extends ContractWrapper<TWFactory> {
implementationAbi: ContractInterface,
initializerFunction: string,
initializerArgs: any[],
eventEmitter: EventEmitter<DeployEvents>,
): Promise<string> {
const encodedFunc = Contract.getInterface(
implementationAbi,
Expand All @@ -151,7 +161,13 @@ export class ContractFactory extends ContractWrapper<TWFactory> {
throw new Error("No ProxyDeployed event found");
}

return events[0].args.proxy;
const contractAddress = events[0].args.proxy;
eventEmitter.emit("contractDeployed", {
contractAddress,
transactionHash: receipt.transactionHash,
});

return contractAddress;
}

/**
Expand Down
8 changes: 8 additions & 0 deletions packages/sdk/src/evm/types/deploy/deploy-events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface DeployEvent {
transactionHash: string;
contractAddress: string;
}

export interface DeployEvents {
contractDeployed: [DeployEvent];
}
1 change: 1 addition & 0 deletions packages/sdk/src/evm/types/deploy/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./deploy-metadata";
export * from "./deploy-events";
5 changes: 3 additions & 2 deletions packages/sdk/test/evm/events.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ describe("Events", async () => {

it("Should emit deploy events", async () => {
// eslint-disable-next-line no-unused-expressions
expect(sdk.deployer.events).to.not.be.undefined;
let txAddress = "";
sdk.deployer.events?.addDeployListener((event) => {
sdk.deployer.addDeployListener((event) => {
console.log(event);
txAddress = event.contractAddress;
});
const address = await sdk.deployer.deployMarketplace({
Expand All @@ -103,6 +103,7 @@ describe("Events", async () => {
// Wait for the async listener to get called
await new Promise((res) => setTimeout(res, 2000));
expect(txAddress).to.equal(address);
sdk.deployer.removeAllDeployListeners();
});

it("should emit Contract events", async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/test/evm/publisher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
TokenERC721__factory,
} from "@thirdweb-dev/contracts-js";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import { assert, expect } from "chai";
import { expect } from "chai";
import { ethers } from "ethers";
import { readFileSync } from "fs";
import invariant from "tiny-invariant";
Expand Down

0 comments on commit bff433e

Please sign in to comment.