@bosonprotocol/core-sdk 1.40.1 → 1.40.2-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/dist/cjs/accounts/interface.d.ts.map +1 -1
  2. package/dist/cjs/core-sdk.d.ts +3 -1
  3. package/dist/cjs/core-sdk.d.ts.map +1 -1
  4. package/dist/cjs/core-sdk.js +5 -1
  5. package/dist/cjs/core-sdk.js.map +1 -1
  6. package/dist/cjs/erc721/handler.d.ts +6 -0
  7. package/dist/cjs/erc721/handler.d.ts.map +1 -1
  8. package/dist/cjs/erc721/handler.js +13 -1
  9. package/dist/cjs/erc721/handler.js.map +1 -1
  10. package/dist/cjs/exchanges/handler.d.ts +8 -1
  11. package/dist/cjs/exchanges/handler.d.ts.map +1 -1
  12. package/dist/cjs/exchanges/handler.js +14 -1
  13. package/dist/cjs/exchanges/handler.js.map +1 -1
  14. package/dist/cjs/exchanges/mixin.d.ts.map +1 -1
  15. package/dist/cjs/exchanges/mixin.js +2 -6
  16. package/dist/cjs/exchanges/mixin.js.map +1 -1
  17. package/dist/cjs/marketplaces/mixin.d.ts +6 -0
  18. package/dist/cjs/marketplaces/mixin.d.ts.map +1 -0
  19. package/dist/cjs/marketplaces/mixin.js +19 -0
  20. package/dist/cjs/marketplaces/mixin.js.map +1 -0
  21. package/dist/cjs/marketplaces/opensea.d.ts +62 -0
  22. package/dist/cjs/marketplaces/opensea.d.ts.map +1 -0
  23. package/dist/cjs/marketplaces/opensea.js +230 -0
  24. package/dist/cjs/marketplaces/opensea.js.map +1 -0
  25. package/dist/cjs/marketplaces/types.d.ts +67 -0
  26. package/dist/cjs/marketplaces/types.d.ts.map +1 -0
  27. package/dist/cjs/marketplaces/types.js +18 -0
  28. package/dist/cjs/marketplaces/types.js.map +1 -0
  29. package/dist/cjs/price-discovery/handler.d.ts +11 -0
  30. package/dist/cjs/price-discovery/handler.d.ts.map +1 -0
  31. package/dist/cjs/price-discovery/handler.js +57 -0
  32. package/dist/cjs/price-discovery/handler.js.map +1 -0
  33. package/dist/cjs/price-discovery/index.d.ts +3 -0
  34. package/dist/cjs/price-discovery/index.d.ts.map +1 -0
  35. package/dist/cjs/price-discovery/index.js +29 -0
  36. package/dist/cjs/price-discovery/index.js.map +1 -0
  37. package/dist/cjs/price-discovery/interface.d.ts +6 -0
  38. package/dist/cjs/price-discovery/interface.d.ts.map +1 -0
  39. package/dist/cjs/price-discovery/interface.js +11 -0
  40. package/dist/cjs/price-discovery/interface.js.map +1 -0
  41. package/dist/cjs/price-discovery/mixin.d.ts +13 -0
  42. package/dist/cjs/price-discovery/mixin.d.ts.map +1 -0
  43. package/dist/cjs/price-discovery/mixin.js +36 -0
  44. package/dist/cjs/price-discovery/mixin.js.map +1 -0
  45. package/dist/cjs/seaport/handler.d.ts +0 -45
  46. package/dist/cjs/seaport/handler.d.ts.map +1 -1
  47. package/dist/cjs/seaport/handler.js +0 -27
  48. package/dist/cjs/seaport/handler.js.map +1 -1
  49. package/dist/cjs/seaport/index.d.ts +1 -1
  50. package/dist/cjs/seaport/index.d.ts.map +1 -1
  51. package/dist/cjs/seaport/index.js +2 -2
  52. package/dist/cjs/seaport/interface.d.ts +71 -0
  53. package/dist/cjs/seaport/interface.d.ts.map +1 -0
  54. package/dist/cjs/seaport/interface.js +42 -0
  55. package/dist/cjs/seaport/interface.js.map +1 -0
  56. package/dist/cjs/seaport/mixin.d.ts +4 -0
  57. package/dist/cjs/seaport/mixin.d.ts.map +1 -0
  58. package/dist/cjs/seaport/mixin.js +8 -0
  59. package/dist/cjs/seaport/mixin.js.map +1 -0
  60. package/dist/cjs/voucher/mixin.d.ts +5 -1
  61. package/dist/cjs/voucher/mixin.d.ts.map +1 -1
  62. package/dist/cjs/voucher/mixin.js +14 -2
  63. package/dist/cjs/voucher/mixin.js.map +1 -1
  64. package/dist/esm/accounts/interface.d.ts.map +1 -1
  65. package/dist/esm/core-sdk.d.ts +3 -1
  66. package/dist/esm/core-sdk.d.ts.map +1 -1
  67. package/dist/esm/core-sdk.js +5 -1
  68. package/dist/esm/core-sdk.js.map +1 -1
  69. package/dist/esm/erc721/handler.d.ts +6 -0
  70. package/dist/esm/erc721/handler.d.ts.map +1 -1
  71. package/dist/esm/erc721/handler.js +9 -0
  72. package/dist/esm/erc721/handler.js.map +1 -1
  73. package/dist/esm/exchanges/handler.d.ts +8 -1
  74. package/dist/esm/exchanges/handler.d.ts.map +1 -1
  75. package/dist/esm/exchanges/handler.js +11 -1
  76. package/dist/esm/exchanges/handler.js.map +1 -1
  77. package/dist/esm/exchanges/mixin.d.ts.map +1 -1
  78. package/dist/esm/exchanges/mixin.js +3 -7
  79. package/dist/esm/exchanges/mixin.js.map +1 -1
  80. package/dist/esm/marketplaces/mixin.d.ts +6 -0
  81. package/dist/esm/marketplaces/mixin.d.ts.map +1 -0
  82. package/dist/esm/marketplaces/mixin.js +15 -0
  83. package/dist/esm/marketplaces/mixin.js.map +1 -0
  84. package/dist/esm/marketplaces/opensea.d.ts +62 -0
  85. package/dist/esm/marketplaces/opensea.d.ts.map +1 -0
  86. package/dist/esm/marketplaces/opensea.js +214 -0
  87. package/dist/esm/marketplaces/opensea.js.map +1 -0
  88. package/dist/esm/marketplaces/types.d.ts +67 -0
  89. package/dist/esm/marketplaces/types.d.ts.map +1 -0
  90. package/dist/esm/marketplaces/types.js +15 -0
  91. package/dist/esm/marketplaces/types.js.map +1 -0
  92. package/dist/esm/price-discovery/handler.d.ts +11 -0
  93. package/dist/esm/price-discovery/handler.d.ts.map +1 -0
  94. package/dist/esm/price-discovery/handler.js +19 -0
  95. package/dist/esm/price-discovery/handler.js.map +1 -0
  96. package/dist/esm/price-discovery/index.d.ts +3 -0
  97. package/dist/esm/price-discovery/index.d.ts.map +1 -0
  98. package/dist/esm/price-discovery/index.js +3 -0
  99. package/dist/esm/price-discovery/index.js.map +1 -0
  100. package/dist/esm/price-discovery/interface.d.ts +6 -0
  101. package/dist/esm/price-discovery/interface.d.ts.map +1 -0
  102. package/dist/esm/price-discovery/interface.js +7 -0
  103. package/dist/esm/price-discovery/interface.js.map +1 -0
  104. package/dist/esm/price-discovery/mixin.d.ts +13 -0
  105. package/dist/esm/price-discovery/mixin.d.ts.map +1 -0
  106. package/dist/esm/price-discovery/mixin.js +21 -0
  107. package/dist/esm/price-discovery/mixin.js.map +1 -0
  108. package/dist/esm/seaport/handler.d.ts +0 -45
  109. package/dist/esm/seaport/handler.d.ts.map +1 -1
  110. package/dist/esm/seaport/handler.js +0 -23
  111. package/dist/esm/seaport/handler.js.map +1 -1
  112. package/dist/esm/seaport/index.d.ts +1 -1
  113. package/dist/esm/seaport/index.d.ts.map +1 -1
  114. package/dist/esm/seaport/index.js +1 -1
  115. package/dist/esm/seaport/index.js.map +1 -1
  116. package/dist/esm/seaport/interface.d.ts +71 -0
  117. package/dist/esm/seaport/interface.d.ts.map +1 -0
  118. package/dist/esm/seaport/interface.js +37 -0
  119. package/dist/esm/seaport/interface.js.map +1 -0
  120. package/dist/esm/seaport/mixin.d.ts +4 -0
  121. package/dist/esm/seaport/mixin.d.ts.map +1 -0
  122. package/dist/esm/seaport/mixin.js +4 -0
  123. package/dist/esm/seaport/mixin.js.map +1 -0
  124. package/dist/esm/voucher/mixin.d.ts +5 -1
  125. package/dist/esm/voucher/mixin.d.ts.map +1 -1
  126. package/dist/esm/voucher/mixin.js +12 -2
  127. package/dist/esm/voucher/mixin.js.map +1 -1
  128. package/package.json +4 -3
  129. package/src/accounts/interface.ts +1 -1
  130. package/src/core-sdk.ts +8 -2
  131. package/src/erc721/handler.ts +15 -0
  132. package/src/exchanges/handler.ts +19 -2
  133. package/src/exchanges/mixin.ts +5 -6
  134. package/src/marketplaces/mixin.ts +24 -0
  135. package/src/marketplaces/opensea.ts +361 -0
  136. package/src/marketplaces/types.ts +73 -0
  137. package/src/price-discovery/handler.ts +37 -0
  138. package/src/price-discovery/index.ts +2 -0
  139. package/src/price-discovery/interface.ts +18 -0
  140. package/src/price-discovery/mixin.ts +30 -0
  141. package/src/seaport/handler.ts +0 -57
  142. package/src/seaport/index.ts +1 -1
  143. package/src/seaport/interface.ts +100 -0
  144. package/src/seaport/mixin.ts +3 -0
  145. package/src/voucher/mixin.ts +21 -2
@@ -0,0 +1,361 @@
1
+ import { formatUnits } from "@ethersproject/units";
2
+ import {
3
+ AssetWithTokenId,
4
+ FulfillmentDataResponse,
5
+ GetNFTResponse,
6
+ NFT,
7
+ OrderAPIOptions,
8
+ OrderSide,
9
+ OrderV2,
10
+ OrdersQueryOptions,
11
+ ProtocolData
12
+ } from "opensea-js";
13
+ import { BigNumber, BigNumberish } from "@ethersproject/bignumber";
14
+ import {
15
+ Listing,
16
+ Marketplace,
17
+ MarketplaceType,
18
+ Order,
19
+ SignedOrder
20
+ } from "./types";
21
+ import {
22
+ ConsiderationItem,
23
+ CreateInputItem,
24
+ CreateOrderAction,
25
+ CreateOrderInput,
26
+ OfferItem,
27
+ OrderParameters,
28
+ OrderUseCase
29
+ } from "@opensea/seaport-js/lib/types";
30
+ import {
31
+ ItemType,
32
+ NO_CONDUIT,
33
+ OPENSEA_CONDUIT_ADDRESS
34
+ } from "@opensea/seaport-js/lib/constants";
35
+ import {
36
+ ContractAddresses,
37
+ PriceDiscoveryStruct,
38
+ Side
39
+ } from "@bosonprotocol/common";
40
+ import {
41
+ CriteriaResolver,
42
+ encodeMatchAdvancedOrders,
43
+ AdvancedOrder,
44
+ Fulfillment
45
+ } from "../seaport/interface";
46
+
47
+ export type OpenSeaListing = {
48
+ asset: AssetWithTokenId;
49
+ accountAddress: string;
50
+ startAmount: BigNumberish;
51
+ endAmount?: BigNumberish;
52
+ quantity?: BigNumberish;
53
+ domain?: string;
54
+ salt?: BigNumberish;
55
+ listingTime?: number;
56
+ expirationTime?: number;
57
+ paymentTokenAddress?: string;
58
+ buyerAddress?: string;
59
+ englishAuction?: boolean;
60
+ excludeOptionalCreatorFees?: boolean;
61
+ };
62
+
63
+ export type OpenSeaSDKHandler = {
64
+ api: {
65
+ apiBaseUrl: string;
66
+ getOrder(order: Omit<OrdersQueryOptions, "limit">): Promise<OrderV2>;
67
+ generateFulfillmentData(
68
+ fulfillerAddress: string,
69
+ orderHash: string,
70
+ protocolAddress: string,
71
+ side: OrderSide
72
+ ): Promise<FulfillmentDataResponse>;
73
+ getNFT(address: string, identifier: string): Promise<GetNFTResponse>;
74
+ postOrder(
75
+ order: ProtocolData,
76
+ apiOptions: OrderAPIOptions
77
+ ): Promise<OrderV2>;
78
+ };
79
+ seaport_v1_6: {
80
+ createOrder(
81
+ input: CreateOrderInput,
82
+ accountAddress?: string,
83
+ exactApproval?: boolean
84
+ ): Promise<OrderUseCase<CreateOrderAction>>;
85
+ };
86
+ createListing(listing: OpenSeaListing): Promise<OrderV2>;
87
+ };
88
+
89
+ export class OpenSeaMarketplace extends Marketplace {
90
+ constructor(
91
+ _type: MarketplaceType,
92
+ protected _handler: OpenSeaSDKHandler,
93
+ protected _contracts: ContractAddresses,
94
+ protected _feeRecipient: string
95
+ ) {
96
+ super(_type);
97
+ }
98
+
99
+ public async createListing(listing: Listing): Promise<Order> {
100
+ const osListing = this.convertListing(listing);
101
+ const osOrder = await this._handler.createListing(osListing);
102
+ return this.convertOsOrder(osOrder);
103
+ }
104
+
105
+ public async createBidOrder(listing: Listing): Promise<Order> {
106
+ const fees = BigNumber.from(listing.price).mul(250).div(10000);
107
+ const domain = undefined;
108
+ const salt = undefined;
109
+ const quantity = undefined;
110
+ const { nft } = await this._handler.api.getNFT(
111
+ listing.asset.contract,
112
+ listing.asset.tokenId
113
+ );
114
+ // getNFTItems(nfts: NFT[], quantities: bigint[]): CreateInputItem[]; is a private method in OpenSea SDK, but need to hack it here
115
+ const considerationAssetItems = this._handler["getNFTItems"](
116
+ [nft],
117
+ // [BigInt(quantity ?? 1)]
118
+ [BigInt(1)]
119
+ );
120
+ const considerationFeeItems = [
121
+ {
122
+ itemType: 1,
123
+ token: listing.exchangeToken.address,
124
+ identifierOrCriteria: "0",
125
+ amount: fees.toString(),
126
+ startAmount: fees.toString(),
127
+ endAmount: fees.toString(),
128
+ recipient: this._feeRecipient
129
+ }
130
+ ];
131
+ const orderParams = {
132
+ offer: [
133
+ {
134
+ itemType: 1,
135
+ token: listing.exchangeToken.address,
136
+ amount: listing.price,
137
+ startAmount: listing.price,
138
+ endAmount: listing.price
139
+ }
140
+ ],
141
+ consideration: [...considerationAssetItems, ...considerationFeeItems],
142
+ endTime: listing.expirationTime.toString(),
143
+ zone: listing.zone || "0x0000000000000000000000000000000000000000",
144
+ domain,
145
+ // salt: BigInt(salt ?? 0).toString(),
146
+ salt: BigInt(0).toString(),
147
+ restrictedByZone: true,
148
+ allowPartialFills: false
149
+ };
150
+
151
+ const { executeAllActions } = await this._handler.seaport_v1_6.createOrder(
152
+ orderParams,
153
+ listing.offerer
154
+ );
155
+ const order = await executeAllActions();
156
+ const protocolAddress = listing.protocolAddress || this._contracts.seaport;
157
+ if (!protocolAddress) {
158
+ throw new Error(
159
+ `Seaport protocol address must be specified in Lsiting or CoreSDK config`
160
+ );
161
+ }
162
+
163
+ const osOrder = await this._handler.api.postOrder(order, {
164
+ protocol: "seaport",
165
+ protocolAddress,
166
+ side: OrderSide.BID
167
+ });
168
+ return this.convertOsOrder(osOrder);
169
+ }
170
+
171
+ public async generateFulfilmentData(asset: {
172
+ contract: string;
173
+ tokenId: string;
174
+ }): Promise<PriceDiscoveryStruct> {
175
+ // Asumption: we're fulfilling a Bid Order (don't know if it makes sense with an Ask order)
176
+ const osOrder = await this._handler.api.getOrder({
177
+ assetContractAddress: asset.contract,
178
+ tokenId: asset.tokenId,
179
+ side: OrderSide.BID
180
+ });
181
+ const orderInfo = this.extractOrderInfo(osOrder.protocolData.parameters);
182
+ const ffd = await this._handler.api.generateFulfillmentData(
183
+ this._contracts.priceDiscoveryClient, // the address of the PriceDiscoveryClient contract, which will call the fulfilment method
184
+ osOrder.orderHash,
185
+ osOrder.protocolAddress,
186
+ osOrder.side
187
+ );
188
+ const inputData = ffd.fulfillment_data.transaction
189
+ .input_data as unknown as {
190
+ orders: AdvancedOrder[];
191
+ criteriaResolvers: CriteriaResolver[];
192
+ fulfillments: Fulfillment[];
193
+ recipient: string;
194
+ };
195
+ const price = inputData.orders[1].parameters.consideration[0].startAmount; // offer price minus opensea fees
196
+ const side = Side.Bid; // ?
197
+ const priceDiscoveryContract = osOrder.protocolAddress; // seaport contract address
198
+ const conduit =
199
+ osOrder.protocolData.parameters.conduitKey === NO_CONDUIT
200
+ ? osOrder.protocolAddress // Seaport is used as conduit
201
+ : OPENSEA_CONDUIT_ADDRESS; // TODO: might not work on mocked networks
202
+ const priceDiscoveryData = encodeMatchAdvancedOrders(
203
+ inputData.orders,
204
+ inputData.criteriaResolvers,
205
+ inputData.fulfillments,
206
+ inputData.recipient
207
+ );
208
+
209
+ return {
210
+ price,
211
+ side,
212
+ priceDiscoveryContract,
213
+ conduit,
214
+ priceDiscoveryData
215
+ };
216
+ }
217
+
218
+ protected convertListing(listing: Listing): OpenSeaListing {
219
+ return {
220
+ asset: {
221
+ tokenAddress: listing.asset.contract,
222
+ tokenId: listing.asset.tokenId
223
+ },
224
+ accountAddress: listing.offerer,
225
+ startAmount: formatUnits(listing.price, listing.exchangeToken.decimals),
226
+ expirationTime: listing.expirationTime,
227
+ paymentTokenAddress: listing.exchangeToken.address,
228
+ englishAuction: listing.auction
229
+ };
230
+ }
231
+
232
+ protected convertOsOrder(osOrder: OrderV2 | undefined): Order | undefined {
233
+ if (!osOrder) {
234
+ return undefined;
235
+ }
236
+ const orderInfo = this.extractOrderInfo(osOrder.protocolData.parameters);
237
+ const side = orderInfo.side === OrderSide.ASK ? Side.Ask : Side.Bid;
238
+ return {
239
+ offerer: orderInfo.offerer,
240
+ side,
241
+ contract: orderInfo.nftContract,
242
+ tokenId: orderInfo.tokenId,
243
+ exchangeToken: {
244
+ address: orderInfo.exchangeToken
245
+ // decimals: ???
246
+ },
247
+ price: orderInfo.price,
248
+ startTime: osOrder.listingTime,
249
+ endTime: osOrder.expirationTime,
250
+ orderHash: osOrder.orderHash,
251
+ protocolAddress: osOrder.protocolAddress,
252
+ maker: osOrder.maker ? { address: osOrder.maker.address } : undefined,
253
+ taker: osOrder.taker ? { address: osOrder.taker.address } : undefined
254
+ };
255
+ }
256
+
257
+ protected extractOrderInfo(
258
+ parameters: OrderParameters,
259
+ side?: OrderSide
260
+ ): {
261
+ offerer: string;
262
+ side: OrderSide;
263
+ nftContract: string;
264
+ tokenId: string;
265
+ price: string;
266
+ fees: string;
267
+ sellerProfit: string;
268
+ exchangeToken: string;
269
+ } {
270
+ let price: string;
271
+ let exchangeToken: string;
272
+ let nft: ConsiderationItem | OfferItem;
273
+ const nftBid = parameters.consideration.find(
274
+ (c) => c.itemType === ItemType.ERC721
275
+ );
276
+ const nftAsk = parameters.offer.find((c) => c.itemType === ItemType.ERC721);
277
+ if (side === OrderSide.BID && !nftBid) {
278
+ console.warn(`NFT not found in order consideration`);
279
+ }
280
+ if (side === OrderSide.ASK && !nftAsk) {
281
+ console.warn(`NFT not found in order offer`);
282
+ }
283
+ if (!side) {
284
+ if (nftBid && !nftAsk) {
285
+ side = OrderSide.BID;
286
+ } else if (!nftBid && nftAsk) {
287
+ side = OrderSide.ASK;
288
+ } else if (nftBid && nftAsk) {
289
+ console.warn(
290
+ `NFT found in both consideration and offer. Unable to detect the order side`
291
+ );
292
+ } else {
293
+ console.warn(
294
+ `No NFT found in consideration or offer. Unable to detect the order side`
295
+ );
296
+ }
297
+ }
298
+ if (side === OrderSide.BID) {
299
+ price = parameters.offer
300
+ .filter((c) => c.itemType === ItemType.ERC20)
301
+ .reduce(
302
+ (total, current) => total.add(current.startAmount),
303
+ BigNumber.from(0)
304
+ )
305
+ .toString();
306
+ exchangeToken = parameters.offer.find(
307
+ (c) => c.itemType === ItemType.ERC20
308
+ )?.token;
309
+ nft = nftBid;
310
+ } else {
311
+ // ASK
312
+ price = parameters.consideration
313
+ .filter((c) => c.itemType === ItemType.ERC20)
314
+ .reduce(
315
+ (total, current) => total.add(current.startAmount),
316
+ BigNumber.from(0)
317
+ )
318
+ .toString();
319
+ exchangeToken = parameters.consideration.find(
320
+ (c) => c.itemType === ItemType.ERC20
321
+ )?.token;
322
+ nft = nftAsk;
323
+ }
324
+ const fees = price
325
+ ? BigNumber.from(price).mul(250).div(10000).toString()
326
+ : "0";
327
+ const sellerProfit = price
328
+ ? BigNumber.from(price).mul(9750).div(10000).toString()
329
+ : "0";
330
+ return {
331
+ offerer: parameters.offerer,
332
+ side,
333
+ nftContract: nft?.token || "0x0",
334
+ tokenId: nft?.identifierOrCriteria || "0x0",
335
+ price,
336
+ fees,
337
+ sellerProfit,
338
+ exchangeToken
339
+ };
340
+ }
341
+
342
+ public async getOrder(
343
+ asset: {
344
+ contract: string;
345
+ tokenId: string;
346
+ },
347
+ side: Side
348
+ ): Promise<SignedOrder> {
349
+ const osOrder = await this._handler.api.getOrder({
350
+ assetContractAddress: asset.contract,
351
+ tokenId: asset.tokenId,
352
+ side: side === Side.Ask ? OrderSide.ASK : OrderSide.BID
353
+ });
354
+ return osOrder
355
+ ? {
356
+ ...this.convertOsOrder(osOrder),
357
+ signature: osOrder.protocolData?.signature
358
+ }
359
+ : undefined;
360
+ }
361
+ }
@@ -0,0 +1,73 @@
1
+ import { PriceDiscoveryStruct, Side } from "@bosonprotocol/common";
2
+ import { OpenSeaSDKHandler } from "./opensea";
3
+
4
+ export type DefaultHandler = {
5
+ // Just here as an example for other type of merketplace in the future
6
+ dummy(): () => void;
7
+ };
8
+
9
+ export enum MarketplaceType {
10
+ DEFAULT,
11
+ OPENSEA
12
+ }
13
+
14
+ export enum OrderSide {}
15
+
16
+ export type MarketplaceHandler = OpenSeaSDKHandler | DefaultHandler;
17
+
18
+ export type Listing = {
19
+ asset: {
20
+ contract: string;
21
+ tokenId: string;
22
+ };
23
+ offerer: string;
24
+ price: string;
25
+ expirationTime: number;
26
+ exchangeToken: { address: string; decimals: number };
27
+ auction: boolean;
28
+ zone?: string;
29
+ protocolAddress?: string;
30
+ };
31
+
32
+ export type Order = {
33
+ offerer: string;
34
+ startTime: number;
35
+ endTime: number;
36
+ orderHash: string;
37
+ protocolAddress: string;
38
+ side: Side;
39
+ maker: {
40
+ address: string;
41
+ };
42
+ taker: {
43
+ address: string;
44
+ };
45
+ contract: string;
46
+ tokenId: string;
47
+ price: string;
48
+ exchangeToken: {
49
+ address: string;
50
+ decimals?: number;
51
+ };
52
+ };
53
+
54
+ export type SignedOrder = Order & {
55
+ signature: string;
56
+ };
57
+
58
+ export abstract class Marketplace {
59
+ constructor(protected _type: MarketplaceType) {}
60
+ public abstract createListing(listing: Listing): Promise<Order>;
61
+ public abstract createBidOrder(listing: Listing): Promise<Order>;
62
+ public abstract getOrder(
63
+ asset: {
64
+ contract: string;
65
+ tokenId: string;
66
+ },
67
+ side: Side
68
+ ): Promise<SignedOrder>;
69
+ public abstract generateFulfilmentData(asset: {
70
+ contract: string;
71
+ tokenId: string;
72
+ }): Promise<PriceDiscoveryStruct>;
73
+ }
@@ -0,0 +1,37 @@
1
+ import {
2
+ Web3LibAdapter,
3
+ PriceDiscoveryStruct,
4
+ TransactionResponse
5
+ } from "@bosonprotocol/common";
6
+ import { BigNumber, BigNumberish } from "@ethersproject/bignumber";
7
+ import * as exchanges from "../exchanges/handler";
8
+ import { getOfferById } from "../offers/subgraph";
9
+ import { AddressZero } from "@ethersproject/constants";
10
+ import { encodeCommitToPriceDiscoveryOffer } from "./interface";
11
+
12
+ export async function commitToPriceDiscoveryOffer(args: {
13
+ contractAddress: string;
14
+ subgraphUrl: string;
15
+ web3Lib: Web3LibAdapter;
16
+ buyer: string;
17
+ tokenIdOrOfferId: BigNumberish;
18
+ priceDiscovery: PriceDiscoveryStruct;
19
+ }): Promise<TransactionResponse> {
20
+ let { offerId } = exchanges.parseTokenId(args.tokenIdOrOfferId);
21
+ if (offerId.eq(0)) {
22
+ offerId = BigNumber.from(args.tokenIdOrOfferId);
23
+ }
24
+ const offer = await getOfferById(args.subgraphUrl, offerId);
25
+
26
+ // TODO: do we need to check allowance?
27
+
28
+ return args.web3Lib.sendTransaction({
29
+ to: args.contractAddress,
30
+ data: encodeCommitToPriceDiscoveryOffer(
31
+ args.buyer,
32
+ args.tokenIdOrOfferId,
33
+ args.priceDiscovery
34
+ ),
35
+ value: offer.exchangeToken.address === AddressZero ? offer.price : "0"
36
+ });
37
+ }
@@ -0,0 +1,2 @@
1
+ export * as iface from "./interface";
2
+ export * as handler from "./handler";
@@ -0,0 +1,18 @@
1
+ import { abis, PriceDiscoveryStruct } from "@bosonprotocol/common";
2
+ import { Interface } from "@ethersproject/abi";
3
+ import { BigNumberish } from "@ethersproject/bignumber";
4
+
5
+ export const priceDiscoveryHandlerIface = new Interface(
6
+ abis.IBosonPriceDiscoveryHandlerABI
7
+ );
8
+
9
+ export function encodeCommitToPriceDiscoveryOffer(
10
+ buyer: string,
11
+ tokenIdOrOfferId: BigNumberish,
12
+ priceDiscovery: PriceDiscoveryStruct
13
+ ) {
14
+ return priceDiscoveryHandlerIface.encodeFunctionData(
15
+ "commitToPriceDiscoveryOffer",
16
+ [buyer, tokenIdOrOfferId, priceDiscovery]
17
+ );
18
+ }
@@ -0,0 +1,30 @@
1
+ import {
2
+ TransactionResponse,
3
+ PriceDiscoveryStruct
4
+ } from "@bosonprotocol/common";
5
+ import { BaseCoreSDK } from "./../mixins/base-core-sdk";
6
+ import { commitToPriceDiscoveryOffer } from "./handler";
7
+ import { BigNumberish } from "@ethersproject/bignumber";
8
+
9
+ export class PriceDiscoveryMixin extends BaseCoreSDK {
10
+ /**
11
+ * Commits to a price discovery offer (first step of an exchange)
12
+ * @param groupToCreate - group with the contract condition
13
+ * @param overrides - Optional overrides.
14
+ * @returns Transaction response.
15
+ */
16
+ public async commitToPriceDiscoveryOffer(
17
+ buyer: string,
18
+ tokenIdOrOfferId: BigNumberish,
19
+ priceDiscovery: PriceDiscoveryStruct
20
+ ): Promise<TransactionResponse> {
21
+ return commitToPriceDiscoveryOffer({
22
+ buyer,
23
+ tokenIdOrOfferId,
24
+ priceDiscovery,
25
+ web3Lib: this._web3Lib,
26
+ subgraphUrl: this._subgraphUrl,
27
+ contractAddress: this._protocolDiamond
28
+ });
29
+ }
30
+ }
@@ -1,57 +0,0 @@
1
- import { BigNumberish } from "@ethersproject/bignumber";
2
- import { Interface } from "@ethersproject/abi";
3
- import { seaportAbi } from "./abi";
4
-
5
- const seaportIface = new Interface(seaportAbi);
6
-
7
- export enum eOrderType {
8
- FULL_OPEN = 0,
9
- PARTIAL_OPEN = 1,
10
- FULL_RESTRICTED = 2,
11
- PARTIAL_RESTRICTED = 3,
12
- CONTRACT = 4
13
- }
14
-
15
- export enum eItemType {
16
- NATIVE = 0,
17
- ERC20 = 1,
18
- ERC721 = 2,
19
- ERC1155 = 3,
20
- ERC721_WITH_CRITERIA = 4,
21
- ERC1155_WITH_CRITERIA = 5
22
- }
23
-
24
- type OfferItem = {
25
- itemType: eItemType;
26
- token: string;
27
- identifierOrCriteria: BigNumberish;
28
- startAmount: BigNumberish;
29
- endAmount: BigNumberish;
30
- };
31
-
32
- type ConsiderationItem = OfferItem & {
33
- recipient: string;
34
- };
35
-
36
- type OrderParameters = {
37
- offerer: string;
38
- zone: string;
39
- offer: OfferItem[];
40
- consideration: ConsiderationItem[];
41
- orderType: eOrderType;
42
- startTime: BigNumberish;
43
- endTime: BigNumberish;
44
- zoneHash: string;
45
- salt: BigNumberish;
46
- conduitKey: string;
47
- totalOriginalConsiderationItems: BigNumberish;
48
- };
49
-
50
- export type Order = {
51
- parameters: OrderParameters;
52
- signature: string;
53
- };
54
-
55
- export function encodeValidate(orders: Order[]) {
56
- return seaportIface.encodeFunctionData("validate", [orders]);
57
- }
@@ -1 +1 @@
1
- export * as handler from "./handler";
1
+ export * as iface from "./interface";
@@ -0,0 +1,100 @@
1
+ import { abis } from "@bosonprotocol/common";
2
+ import { Interface } from "@ethersproject/abi";
3
+ import { BigNumberish } from "@ethersproject/bignumber";
4
+
5
+ const seaportIface = new Interface(abis.SeaportABI);
6
+
7
+ export enum eOrderType {
8
+ FULL_OPEN = 0,
9
+ PARTIAL_OPEN = 1,
10
+ FULL_RESTRICTED = 2,
11
+ PARTIAL_RESTRICTED = 3,
12
+ CONTRACT = 4
13
+ }
14
+
15
+ export enum eItemType {
16
+ NATIVE = 0,
17
+ ERC20 = 1,
18
+ ERC721 = 2,
19
+ ERC1155 = 3,
20
+ ERC721_WITH_CRITERIA = 4,
21
+ ERC1155_WITH_CRITERIA = 5
22
+ }
23
+
24
+ type OfferItem = {
25
+ itemType: eItemType;
26
+ token: string;
27
+ identifierOrCriteria: BigNumberish;
28
+ startAmount: BigNumberish;
29
+ endAmount: BigNumberish;
30
+ };
31
+
32
+ type ConsiderationItem = OfferItem & {
33
+ recipient: string;
34
+ };
35
+
36
+ type OrderParameters = {
37
+ offerer: string;
38
+ zone: string;
39
+ offer: OfferItem[];
40
+ consideration: ConsiderationItem[];
41
+ orderType: eOrderType;
42
+ startTime: BigNumberish;
43
+ endTime: BigNumberish;
44
+ zoneHash: string;
45
+ salt: BigNumberish;
46
+ conduitKey: string;
47
+ totalOriginalConsiderationItems: BigNumberish;
48
+ };
49
+
50
+ export type Order = {
51
+ parameters: OrderParameters;
52
+ signature: string;
53
+ };
54
+
55
+ export type AdvancedOrder = Order & {
56
+ numerator: BigNumberish;
57
+ denominator: BigNumberish;
58
+ extraData: string;
59
+ };
60
+
61
+ export enum Side {
62
+ OFFER = 0, // items that can be spent
63
+ CONSIDERATION = 1 // items that must be received
64
+ }
65
+
66
+ export type CriteriaResolver = {
67
+ orderIndex: BigNumberish;
68
+ side: number;
69
+ index: BigNumberish;
70
+ identifier: BigNumberish;
71
+ criteriaProof: string[];
72
+ };
73
+
74
+ export type Fulfillment = {
75
+ offerComponents: FulfillmentComponent[];
76
+ considerationComponents: FulfillmentComponent[];
77
+ };
78
+
79
+ export type FulfillmentComponent = {
80
+ orderIndex: BigNumberish;
81
+ itemIndex: BigNumberish;
82
+ };
83
+
84
+ export function encodeValidate(orders: Order[]) {
85
+ return seaportIface.encodeFunctionData("validate", [orders]);
86
+ }
87
+
88
+ export function encodeMatchAdvancedOrders(
89
+ advancedOrders: AdvancedOrder[],
90
+ criteriaResolvers: CriteriaResolver[],
91
+ fulfillments: Fulfillment[],
92
+ recipient: string
93
+ ) {
94
+ return seaportIface.encodeFunctionData("matchAdvancedOrders", [
95
+ advancedOrders,
96
+ criteriaResolvers,
97
+ fulfillments,
98
+ recipient
99
+ ]);
100
+ }
@@ -0,0 +1,3 @@
1
+ import { BaseCoreSDK } from "./../mixins/base-core-sdk";
2
+
3
+ export class SeaportMixin extends BaseCoreSDK {}