diff --git a/src/client.ts b/src/client.ts index df4d36a..3c40854 100644 --- a/src/client.ts +++ b/src/client.ts @@ -253,7 +253,7 @@ export class HypercertClient implements HypercertClientInterface { } const safeTransactions = new SafeTransactions(overrides.safeAddress, this._walletClient, this._getContract()); - return safeTransactions.mintHypercert(method, params, overrides); + return safeTransactions.sendTransaction(method, params, overrides); } const request = await this.simulateRequest(account, method, params, overrides); @@ -469,6 +469,8 @@ export class HypercertClient implements HypercertClientInterface { * This function handles the claiming of a fraction from an allowlist for the connected account. * It verifies the Merkle proof if a root is provided and then submits the minting request. * + * If you provide `overrides.safeAddress`, the transaction will be sent as a Safe transaction instead. + * * @param params - The parameters for the claim operation. * @param params.hypercertTokenId - The ID of the hypercert token to claim. * @param params.units - The number of units to claim. @@ -497,12 +499,20 @@ export class HypercertClient implements HypercertClientInterface { ); } - const request = await this.simulateRequest( - account, - "mintClaimFromAllowlist", - [account.address, proof, hypercertTokenId, units], - overrides, - ); + const accountAddress = overrides?.safeAddress ?? account.address; + const params = [accountAddress, proof, hypercertTokenId, units]; + + // If a safe address is provided, use the SafeTransactions class + if (overrides?.safeAddress) { + if (!this._walletClient) { + throw new ClientError("Safe address provided but no wallet client found"); + } + + const safeTransactions = new SafeTransactions(overrides.safeAddress, this._walletClient, this._getContract()); + return safeTransactions.sendTransaction("mintClaimFromAllowlist", params, overrides); + } + + const request = await this.simulateRequest(account, "mintClaimFromAllowlist", params, overrides); return this.submitRequest(request); }; diff --git a/src/safe/SafeTransactions.ts b/src/safe/SafeTransactions.ts index eff6902..63e7d0b 100644 --- a/src/safe/SafeTransactions.ts +++ b/src/safe/SafeTransactions.ts @@ -30,7 +30,7 @@ export class SafeTransactions { }); } - public mintHypercert = ( + public sendTransaction = ( functionName: string, params: unknown[], overrides?: SupportedOverrides, diff --git a/test/safe/transactions.test.ts b/test/safe/transactions.test.ts index ee0e74e..4322c74 100644 --- a/test/safe/transactions.test.ts +++ b/test/safe/transactions.test.ts @@ -40,7 +40,7 @@ describe("SafeTransactions", () => { } as any); }); - describe("mintHypercert", () => { + describe("sendTransaction", () => { const validParams = [senderAddress, 1000n, "0xcid", 0]; it("correctly encodes function data for transaction", async () => { @@ -52,7 +52,7 @@ describe("SafeTransactions", () => { args: validParams, }); - await safeTransactions.mintHypercert(functionName, validParams, { + await safeTransactions.sendTransaction(functionName, validParams, { safeAddress, }); @@ -70,7 +70,7 @@ describe("SafeTransactions", () => { it("uses correct nonce from API", async () => { safeApiKitStub.getNextNonce.resolves("42"); - await safeTransactions.mintHypercert("mintClaim", validParams, { + await safeTransactions.sendTransaction("mintClaim", validParams, { safeAddress, }); @@ -95,7 +95,7 @@ describe("SafeTransactions", () => { ); try { - await safeTransactions.mintHypercert("mintClaim", validParams, { safeAddress }); + await safeTransactions.sendTransaction("mintClaim", validParams, { safeAddress }); expect.fail("Should throw ClientError"); } catch (e) { expect(e).to.be.instanceOf(ClientError); @@ -104,7 +104,7 @@ describe("SafeTransactions", () => { }); it("follows complete transaction flow", async () => { - const hash = await safeTransactions.mintHypercert("mintClaim", validParams, { + const hash = await safeTransactions.sendTransaction("mintClaim", validParams, { safeAddress, }); @@ -123,7 +123,7 @@ describe("SafeTransactions", () => { safeApiKitStub.proposeTransaction.rejects(new Error(errorMessage)); try { - await safeTransactions.mintHypercert("mintClaim", validParams, { safeAddress }); + await safeTransactions.sendTransaction("mintClaim", validParams, { safeAddress }); expect.fail("Should throw SafeTransactionError"); } catch (e) { expect(e).to.be.instanceOf(SafeTransactionError); @@ -142,7 +142,7 @@ describe("SafeTransactions", () => { connectedSafeStub.createTransaction.rejects(new Error(errorMessage)); try { - await safeTransactions.mintHypercert("mintClaim", [senderAddress, 1000n, "0xcid", 0], { safeAddress }); + await safeTransactions.sendTransaction("mintClaim", [senderAddress, 1000n, "0xcid", 0], { safeAddress }); expect.fail("Should throw SafeTransactionError"); } catch (e) { expect(e).to.be.instanceOf(SafeTransactionError); @@ -155,7 +155,7 @@ describe("SafeTransactions", () => { }); it("properly proposes transaction with correct parameters", async () => { - await safeTransactions.mintHypercert("mintClaim", [senderAddress, 1000n, "0xcid", 0], { safeAddress }); + await safeTransactions.sendTransaction("mintClaim", [senderAddress, 1000n, "0xcid", 0], { safeAddress }); const proposeCall = safeApiKitStub.proposeTransaction.getCall(0); expect(proposeCall.args[0]).to.deep.include({ @@ -171,6 +171,29 @@ describe("SafeTransactions", () => { }); }); }); + + describe("constructor", () => { + it("throws error when wallet client has no chain ID", () => { + chai.Assertion.expectAssertions(2); + + const invalidWalletClient = { ...walletClient, chain: undefined }; + + try { + new SafeTransactions( + safeAddress, + invalidWalletClient as any, + { + address: contractAddress, + abi: HypercertMinterAbi, + } as any, + ); + expect.fail("Should throw Error"); + } catch (e) { + expect(e).to.be.instanceOf(Error); + expect((e as Error).message).to.eq("No chain ID found in wallet client"); + } + }); + }); }); function createConnectedSafeStub(contractAddress: string, mockTxHash: `0x${string}`, mockSignature: `0x${string}`) {