|
| 1 | +# Synthesis: `createOfferAndCommit` in core-sdk.test.ts |
| 2 | + |
| 3 | +## What the method does |
| 4 | + |
| 5 | +`createOfferAndCommit` (helper in `e2e/tests/utils.ts`) atomically: |
| 6 | +1. Has the **offer creator** sign the offer (`signFullOffer`) |
| 7 | +2. Has the **committer** broadcast a single blockchain transaction that both *creates* the offer and *commits* to it |
| 8 | +3. Waits for the tx receipt, extracts `offerId` and `exchangeId` from logs |
| 9 | +4. Waits for the graph node to index the transaction |
| 10 | +5. Returns `{ offer, exchange }` fetched from the subgraph |
| 11 | + |
| 12 | +Signature: |
| 13 | +```ts |
| 14 | +createOfferAndCommit( |
| 15 | + committerCoreSDK: CoreSDK, // the party who sends the tx and commits |
| 16 | + offerCreatorCoreSDK: CoreSDK, // the party who signs the offer |
| 17 | + fullOfferArgsUnsigned: Omit<FullOfferArgs, "signature"> |
| 18 | +): Promise<{ offer, exchange }> |
| 19 | +``` |
| 20 | + |
| 21 | +The underlying SDK method `CoreSDK.createOfferAndCommit()` also accepts `{ returnTxInfo: true }` to return raw tx data instead of broadcasting. |
| 22 | + |
| 23 | +--- |
| 24 | + |
| 25 | +## Two Main Use-Cases |
| 26 | + |
| 27 | +### 1. Seller-Initiated Offers (`describe("seller-initiated offers")`) |
| 28 | +- **Offer creator** = seller (`sellerCoreSDK`) |
| 29 | +- **Committer** = buyer (`buyerCoreSDK`) |
| 30 | +- The seller pre-signs the offer; the buyer calls the combined tx |
| 31 | +- `quantityInitial` > 1 → multiple buyers can commit sequentially |
| 32 | +- After first commit: `quantityAvailable = quantityInitial - 1` |
| 33 | + |
| 34 | +### 2. Buyer-Initiated Offers (`describe("buyer-initiated offers")`) |
| 35 | +- **Offer creator** = buyer (`buyerCoreSDK`) |
| 36 | +- **Committer** = seller (`sellerCoreSDK`) |
| 37 | +- The buyer pre-signs the offer; the seller calls the combined tx |
| 38 | +- `quantityAvailable` is always **1** → offer is sold out immediately after one commit |
| 39 | +- A second buyer attempting to commit gets: `"Offer with id X is sold out"` |
| 40 | + |
| 41 | +--- |
| 42 | + |
| 43 | +## Prerequisites |
| 44 | + |
| 45 | +### 1. Funded wallets for both parties |
| 46 | +`initSellerAndBuyerSDKs` (`utils.ts:263`) creates two fresh wallets (seller + buyer), each funded with ETH from a seed wallet. Both parties must have enough native ETH to pay for gas (and for the commit price in native-ETH offers). |
| 47 | + |
| 48 | +### 2. Seller account registered on-chain — `createSeller` is mandatory |
| 49 | +`createSeller` (`utils.ts`) must be called before any `createOfferAndCommit`. It: |
| 50 | +- Stores seller metadata on IPFS |
| 51 | +- Calls `coreSDK.createSeller()` on-chain (registering `assistant`, `admin`, `treasury` addresses) |
| 52 | +- Returns the `sellerId` that is embedded in `fullOfferArgsUnsigned` |
| 53 | + |
| 54 | +Without a registered seller, there is no `sellerId` to reference and the offer cannot be created. |
| 55 | + |
| 56 | +### 3. Dispute resolver must exist and be active |
| 57 | +`checkDisputeResolver` (`core-sdk.test.ts:2215`) asserts that: |
| 58 | +- Dispute resolver #1 exists on-chain |
| 59 | +- `dr.active === true` |
| 60 | +- The seller is either on its allow-list or the allow-list is open (length = 0) |
| 61 | + |
| 62 | +This is a protocol-level requirement: every offer must reference a valid, active dispute resolver that accepts the seller. |
| 63 | + |
| 64 | +### 4. ERC20 tokens minted and approved (ERC20 offers only) |
| 65 | +For ERC20-token offers, `ensureMintedAndAllowedTokens` must be called for both wallets before committing. |
| 66 | + |
| 67 | +### 5. `fullOfferArgsUnsigned` correctly built |
| 68 | +`buildFullOfferArgs` must receive the correct `committer`/`offerCreator` addresses, `sellerId`, `creator` enum (`OfferCreator.Seller` or `OfferCreator.Buyer`), and `quantityAvailable` (> 1 for seller-initiated, = 1 for buyer-initiated). |
| 69 | + |
| 70 | +### Summary table |
| 71 | + |
| 72 | +| Prerequisite | Seller-initiated | Buyer-initiated | |
| 73 | +|---|---|---| |
| 74 | +| Both wallets funded with ETH | ✅ | ✅ | |
| 75 | +| `createSeller` called → `sellerId` obtained | ✅ | ✅ | |
| 76 | +| Dispute resolver active & accepts seller | ✅ | ✅ | |
| 77 | +| ERC20 minted + approved (ERC20 tests only) | ✅ | ✅ | |
| 78 | +| `fullOfferArgsUnsigned` built with correct roles | ✅ | ✅ | |
| 79 | +| `quantityAvailable` > 1 | ✅ | ❌ (= 1) | |
| 80 | + |
| 81 | +--- |
| 82 | + |
| 83 | +## Test Scenarios Covered |
| 84 | + |
| 85 | +### Happy paths |
| 86 | +| Test | Committer | Creator | Token | |
| 87 | +|---|---|---|---| |
| 88 | +| Buyer commits to native offer | buyer | seller | ETH | |
| 89 | +| Buyer commits to ERC20 offer | buyer | seller | ERC20 | |
| 90 | +| Seller commits to native offer | seller | buyer | ETH | |
| 91 | +| Seller commits to ERC20 offer | seller | buyer | ERC20 | |
| 92 | +| Another buyer commits to same seller offer | buyer #2 | seller | ETH | |
| 93 | + |
| 94 | +### Error / void paths |
| 95 | +| Test | Who voids | When | Error | |
| 96 | +|---|---|---|---| |
| 97 | +| `voidOffer` after first commit | seller (or buyer) | after commit | `offer.voided = true`, next commit fails | |
| 98 | +| `voidNonListedOffer` before first commit | seller (or buyer) | before commit | `"The offer has been voided"` | |
| 99 | +| `voidNonListedOfferBatch` (3 offers) | seller (or buyer) | before commit | `"The offer has been voided"` | |
| 100 | +| Buyer-initiated, second commit | n/a | after first commit | `"Offer with id X is sold out"` | |
| 101 | + |
| 102 | +### Utility / inspection |
| 103 | +| Test | Purpose | |
| 104 | +|---|---| |
| 105 | +| `returnTxInfo: true` | Returns `{ data, to, value }` without broadcasting | |
| 106 | + |
| 107 | +--- |
| 108 | + |
| 109 | +## Key Assertions (successful path) |
| 110 | +- `offer` is truthy and `offer.voided` is falsy |
| 111 | +- `offer.seller.id` matches the seller's id |
| 112 | +- `offer.quantityAvailable = quantityInitial - 1` (seller-initiated) or `0` (buyer-initiated) |
| 113 | +- `exchange.state === ExchangeState.COMMITTED` |
| 114 | +- `exchange.buyer.wallet` matches the buyer's address |
| 115 | + |
| 116 | +--- |
| 117 | + |
| 118 | +## Files |
| 119 | +- Helper definition: `e2e/tests/utils.ts:660` |
| 120 | +- Test file: `e2e/tests/core-sdk.test.ts` (seller-initiated ~L245–430, buyer-initiated ~L534–680) |
0 commit comments