Skip to content

Commit 52848ca

Browse files
Add signMetaTxCommitToBuyerOffer to meta-tx handler, mixin, and e2e tests
Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com>
1 parent 0c5609b commit 52848ca

3 files changed

Lines changed: 141 additions & 4 deletions

File tree

e2e/tests/meta-tx.test.ts

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ZERO_ADDRESS } from "./../../packages/core-sdk/tests/mocks";
22
import { BigNumberish } from "@ethersproject/bignumber";
3+
import { parseEther } from "@ethersproject/units";
34
import { Wallet, BigNumber, constants } from "ethers";
45
import { OfferFieldsFragment } from "../../packages/core-sdk/src/subgraph";
56
import { mockCreateOfferArgs } from "../../packages/common/tests/mocks";
@@ -26,12 +27,19 @@ import {
2627
createOfferWithCondition,
2728
getCollectionMetadataUri,
2829
createRandomWallet,
29-
META_TX_API_ID_VOUCHER
30+
META_TX_API_ID_VOUCHER,
31+
createDisputeResolver,
32+
deployerWallet,
33+
initSellerAndBuyerSDKs
3034
} from "./utils";
3135
import { CoreSDK, forwarder } from "../../packages/core-sdk/src";
3236
import EvaluationMethod from "../../contracts/protocol-contracts/scripts/domain/EvaluationMethod";
3337
import TokenType from "../../contracts/protocol-contracts/scripts/domain/TokenType";
34-
import { AuthTokenType, GatingType } from "../../packages/common";
38+
import { AuthTokenType, GatingType, OfferCreator } from "../../packages/common";
39+
import {
40+
MSEC_PER_DAY,
41+
MSEC_PER_SEC
42+
} from "./../../packages/common/src/utils/timestamp";
3543

3644
const sellerWallet = seedWallet7; // be sure the seedWallet is not used by another test (to allow concurrent run)
3745
const sellerAddress = sellerWallet.address;
@@ -724,6 +732,98 @@ describe("meta-tx", () => {
724732
});
725733
});
726734

735+
describe("#signMetaTxCommitToBuyerOffer()", () => {
736+
test("native exchange token buyer-initiated offer", async () => {
737+
const exchangeToken = constants.AddressZero;
738+
const drFeeAmount = parseEther("0.005");
739+
740+
// Create a dispute resolver with a fee amount
741+
const { fundedWallet: drFundedWallet } =
742+
await initCoreSDKWithFundedWallet(sellerWallet);
743+
const drAddress = drFundedWallet.address.toLowerCase();
744+
const { disputeResolver } = await createDisputeResolver(
745+
drFundedWallet,
746+
deployerWallet,
747+
{
748+
assistant: drAddress,
749+
admin: drAddress,
750+
treasury: drAddress,
751+
metadataUri: "",
752+
escalationResponsePeriodInMS:
753+
90 * MSEC_PER_DAY - 1 * MSEC_PER_SEC,
754+
fees: [
755+
{
756+
feeAmount: drFeeAmount,
757+
tokenAddress: exchangeToken,
758+
tokenName: "Native"
759+
}
760+
],
761+
sellerAllowList: []
762+
}
763+
);
764+
765+
// Create fresh buyer/seller wallets
766+
const {
767+
sellerCoreSDK: sellerCoreSDKBuyer,
768+
buyerCoreSDK: buyerCoreSDKBuyer,
769+
sellerWallet: sellerFundedWallet
770+
} = await initSellerAndBuyerSDKs(sellerWallet);
771+
772+
// Buyer creates a buyer-initiated offer
773+
const buyerInitiatedOffer = await createOffer(buyerCoreSDKBuyer, {
774+
creator: OfferCreator.Buyer,
775+
quantityAvailable: 1,
776+
disputeResolverId: disputeResolver.id,
777+
exchangeToken
778+
});
779+
780+
// Buyer deposits offer.price to allow the seller to commit
781+
const buyerDepositTx = await buyerCoreSDKBuyer.depositFunds(
782+
buyerInitiatedOffer.buyerId,
783+
buyerInitiatedOffer.price,
784+
exchangeToken
785+
);
786+
await buyerCoreSDKBuyer.waitForGraphNodeIndexing(buyerDepositTx);
787+
788+
// Seller creates a seller account
789+
const seller = await createSeller(
790+
sellerCoreSDKBuyer,
791+
sellerFundedWallet.address
792+
);
793+
794+
// Seller deposits DR fee amount
795+
const sellerDepositTx = await sellerCoreSDKBuyer.depositFunds(
796+
seller.id,
797+
drFeeAmount,
798+
exchangeToken
799+
);
800+
await sellerCoreSDKBuyer.waitForGraphNodeIndexing(sellerDepositTx);
801+
802+
const nonce = Date.now();
803+
804+
// Seller signs meta tx for commitToBuyerOffer
805+
const { r, s, v, functionName, functionSignature } =
806+
await sellerCoreSDKBuyer.signMetaTxCommitToBuyerOffer({
807+
offerId: buyerInitiatedOffer.id,
808+
sellerParams: {},
809+
nonce
810+
});
811+
812+
// Relayer executes meta tx on behalf of seller
813+
const metaTx = await sellerCoreSDKBuyer.relayMetaTransaction({
814+
functionName,
815+
functionSignature,
816+
nonce,
817+
sigR: r,
818+
sigS: s,
819+
sigV: v
820+
});
821+
const metaTxReceipt = await metaTx.wait();
822+
expect(metaTxReceipt.transactionHash).toBeTruthy();
823+
expect(BigNumber.from(metaTxReceipt.effectiveGasPrice).gt(0)).toBe(true);
824+
});
825+
});
826+
727827
describe("#signMetaTxRedeemVoucher()", () => {
728828
test("non-native exchange token offer", async () => {
729829
const commitTx = await buyerCoreSDK.commitToOffer(offerToCommit.id);

packages/core-sdk/src/meta-tx/handler.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
UpdateSellerArgs,
1212
OptInToSellerUpdateArgs,
1313
envConfigs,
14-
abis
14+
abis,
15+
SellerOfferArgs
1516
} from "@bosonprotocol/common";
1617
import { storeMetadataOnTheGraph } from "../offers/storage";
1718
import { BigNumber, BigNumberish } from "@ethersproject/bignumber";
@@ -24,7 +25,8 @@ import {
2425
} from "../accounts/interface";
2526
import {
2627
bosonExchangeCommitHandlerIface,
27-
bosonExchangeHandlerIface
28+
bosonExchangeHandlerIface,
29+
encodeCommitToBuyerOffer
2830
} from "../exchanges/interface";
2931
import {
3032
bosonOfferHandlerIface,
@@ -944,6 +946,22 @@ export async function signMetaTxCommitToConditionalOffer(
944946
};
945947
}
946948

949+
export async function signMetaTxCommitToBuyerOffer(
950+
args: BaseMetaTxArgs & {
951+
offerId: BigNumberish;
952+
sellerParams: SellerOfferArgs;
953+
}
954+
): Promise<SignedMetaTx> {
955+
const functionName =
956+
"commitToBuyerOffer(uint256,(uint256,(address[],uint256[]),address))";
957+
958+
return signMetaTx({
959+
...args,
960+
functionName,
961+
functionSignature: encodeCommitToBuyerOffer(args.offerId, args.sellerParams)
962+
});
963+
}
964+
947965
export async function signMetaTxCancelVoucher(
948966
args: BaseMetaTxArgs & {
949967
exchangeId: BigNumberish;

packages/core-sdk/src/meta-tx/mixin.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,25 @@ export class MetaTxMixin<T extends Web3LibAdapter> extends BaseCoreSDK<T> {
634634
});
635635
}
636636

637+
/**
638+
* Encodes and signs a meta transaction for `commitToBuyerOffer` that can be relayed.
639+
* @param args - Meta transaction args.
640+
* @returns Signature.
641+
*/
642+
public async signMetaTxCommitToBuyerOffer(
643+
args: Omit<
644+
Parameters<typeof handler.signMetaTxCommitToBuyerOffer>[0],
645+
"web3Lib" | "metaTxHandlerAddress" | "chainId"
646+
>
647+
) {
648+
return handler.signMetaTxCommitToBuyerOffer({
649+
web3Lib: this._web3Lib,
650+
metaTxHandlerAddress: this._protocolDiamond,
651+
chainId: this._chainId,
652+
...args
653+
});
654+
}
655+
637656
/**
638657
* Encodes and signs a meta transaction for `cancelVoucher` that can be relayed.
639658
* @param args - Meta transaction args.

0 commit comments

Comments
 (0)