@opensea/seaport-js 1.0.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 (74) hide show
  1. package/README.md +45 -0
  2. package/lib/abi/ERC1155.d.ts +29 -0
  3. package/lib/abi/ERC1155.js +319 -0
  4. package/lib/abi/ERC1155.js.map +1 -0
  5. package/lib/abi/ERC20.d.ts +29 -0
  6. package/lib/abi/ERC20.js +317 -0
  7. package/lib/abi/ERC20.js.map +1 -0
  8. package/lib/abi/ERC721.d.ts +29 -0
  9. package/lib/abi/ERC721.js +337 -0
  10. package/lib/abi/ERC721.js.map +1 -0
  11. package/lib/abi/Seaport.d.ts +112 -0
  12. package/lib/abi/Seaport.js +2585 -0
  13. package/lib/abi/Seaport.js.map +1 -0
  14. package/lib/constants.d.ts +49 -0
  15. package/lib/constants.js +73 -0
  16. package/lib/constants.js.map +1 -0
  17. package/lib/index.d.ts +2 -0
  18. package/lib/index.js +6 -0
  19. package/lib/index.js.map +1 -0
  20. package/lib/seaport.d.ts +181 -0
  21. package/lib/seaport.js +720 -0
  22. package/lib/seaport.js.map +1 -0
  23. package/lib/typechain/ERC1155.d.ts +189 -0
  24. package/lib/typechain/ERC1155.js +3 -0
  25. package/lib/typechain/ERC1155.js.map +1 -0
  26. package/lib/typechain/ERC20.d.ts +209 -0
  27. package/lib/typechain/ERC20.js +3 -0
  28. package/lib/typechain/ERC20.js.map +1 -0
  29. package/lib/typechain/ERC721.d.ts +220 -0
  30. package/lib/typechain/ERC721.js +3 -0
  31. package/lib/typechain/ERC721.js.map +1 -0
  32. package/lib/typechain/Seaport.d.ts +686 -0
  33. package/lib/typechain/Seaport.js +3 -0
  34. package/lib/typechain/Seaport.js.map +1 -0
  35. package/lib/typechain/common.d.ts +21 -0
  36. package/lib/typechain/common.js +3 -0
  37. package/lib/typechain/common.js.map +1 -0
  38. package/lib/types.d.ts +207 -0
  39. package/lib/types.js +3 -0
  40. package/lib/types.js.map +1 -0
  41. package/lib/utils/approval.d.ts +9 -0
  42. package/lib/utils/approval.js +108 -0
  43. package/lib/utils/approval.js.map +1 -0
  44. package/lib/utils/balance.d.ts +4 -0
  45. package/lib/utils/balance.js +86 -0
  46. package/lib/utils/balance.js.map +1 -0
  47. package/lib/utils/balanceAndApprovalCheck.d.ts +108 -0
  48. package/lib/utils/balanceAndApprovalCheck.js +322 -0
  49. package/lib/utils/balanceAndApprovalCheck.js.map +1 -0
  50. package/lib/utils/criteria.d.ts +14 -0
  51. package/lib/utils/criteria.js +91 -0
  52. package/lib/utils/criteria.js.map +1 -0
  53. package/lib/utils/fulfill.d.ts +84 -0
  54. package/lib/utils/fulfill.js +573 -0
  55. package/lib/utils/fulfill.js.map +1 -0
  56. package/lib/utils/gcd.d.ts +3 -0
  57. package/lib/utils/gcd.js +25 -0
  58. package/lib/utils/gcd.js.map +1 -0
  59. package/lib/utils/item.d.ts +29 -0
  60. package/lib/utils/item.js +136 -0
  61. package/lib/utils/item.js.map +1 -0
  62. package/lib/utils/match.d.ts +54 -0
  63. package/lib/utils/match.js +56 -0
  64. package/lib/utils/match.js.map +1 -0
  65. package/lib/utils/merkletree.d.ts +11 -0
  66. package/lib/utils/merkletree.js +32 -0
  67. package/lib/utils/merkletree.js.map +1 -0
  68. package/lib/utils/order.d.ts +37 -0
  69. package/lib/utils/order.js +224 -0
  70. package/lib/utils/order.js.map +1 -0
  71. package/lib/utils/usecase.d.ts +4 -0
  72. package/lib/utils/usecase.js +158 -0
  73. package/lib/utils/usecase.js.map +1 -0
  74. package/package.json +93 -0
@@ -0,0 +1,29 @@
1
+ import { BigNumber } from "ethers";
2
+ import type { InputCriteria, Item, Order, OrderParameters } from "../types";
3
+ export declare const isCurrencyItem: ({ itemType }: Item) => boolean;
4
+ export declare const isNativeCurrencyItem: ({ itemType }: Item) => boolean;
5
+ export declare const isErc20Item: (itemType: Item["itemType"]) => boolean;
6
+ export declare const isErc721Item: (itemType: Item["itemType"]) => boolean;
7
+ export declare const isErc1155Item: (itemType: Item["itemType"]) => boolean;
8
+ export declare const isCriteriaItem: (itemType: Item["itemType"]) => boolean;
9
+ export declare type TimeBasedItemParams = {
10
+ isConsiderationItem?: boolean;
11
+ currentBlockTimestamp: number;
12
+ ascendingAmountTimestampBuffer: number;
13
+ } & Pick<OrderParameters, "startTime" | "endTime">;
14
+ export declare const getPresentItemAmount: ({ startAmount, endAmount, timeBasedItemParams, }: Pick<Item, "startAmount" | "endAmount"> & {
15
+ timeBasedItemParams?: TimeBasedItemParams | undefined;
16
+ }) => BigNumber;
17
+ export declare const getSummedTokenAndIdentifierAmounts: ({ items, criterias, timeBasedItemParams, }: {
18
+ items: Item[];
19
+ criterias: InputCriteria[];
20
+ timeBasedItemParams?: TimeBasedItemParams | undefined;
21
+ }) => Record<string, Record<string, BigNumber>>;
22
+ /**
23
+ * Returns the maximum size of units possible for the order
24
+ * If any of the items on a partially fillable order specify a different "startAmount" and "endAmount
25
+ * (e.g. they are ascending-amount or descending-amount items), the fraction will be applied to both amounts
26
+ * prior to determining the current price. This ensures that cleanly divisible amounts can be chosen when
27
+ * constructing the order without a dependency on the time when the order is ultimately fulfilled.
28
+ */
29
+ export declare const getMaximumSizeForOrder: ({ parameters: { offer, consideration }, }: Order) => BigNumber;
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __read = (this && this.__read) || function (o, n) {
14
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
15
+ if (!m) return o;
16
+ var i = m.call(o), r, ar = [], e;
17
+ try {
18
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
19
+ }
20
+ catch (error) { e = { error: error }; }
21
+ finally {
22
+ try {
23
+ if (r && !r.done && (m = i["return"])) m.call(i);
24
+ }
25
+ finally { if (e) throw e.error; }
26
+ }
27
+ return ar;
28
+ };
29
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
30
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
31
+ if (ar || !(i in from)) {
32
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
33
+ ar[i] = from[i];
34
+ }
35
+ }
36
+ return to.concat(ar || Array.prototype.slice.call(from));
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.getMaximumSizeForOrder = exports.getSummedTokenAndIdentifierAmounts = exports.getPresentItemAmount = exports.isCriteriaItem = exports.isErc1155Item = exports.isErc721Item = exports.isErc20Item = exports.isNativeCurrencyItem = exports.isCurrencyItem = void 0;
40
+ var ethers_1 = require("ethers");
41
+ var constants_1 = require("../constants");
42
+ var criteria_1 = require("./criteria");
43
+ var gcd_1 = require("./gcd");
44
+ var isCurrencyItem = function (_a) {
45
+ var itemType = _a.itemType;
46
+ return [constants_1.ItemType.NATIVE, constants_1.ItemType.ERC20].includes(itemType);
47
+ };
48
+ exports.isCurrencyItem = isCurrencyItem;
49
+ var isNativeCurrencyItem = function (_a) {
50
+ var itemType = _a.itemType;
51
+ return itemType === constants_1.ItemType.NATIVE;
52
+ };
53
+ exports.isNativeCurrencyItem = isNativeCurrencyItem;
54
+ var isErc20Item = function (itemType) {
55
+ return itemType === constants_1.ItemType.ERC20;
56
+ };
57
+ exports.isErc20Item = isErc20Item;
58
+ var isErc721Item = function (itemType) {
59
+ return [constants_1.ItemType.ERC721, constants_1.ItemType.ERC721_WITH_CRITERIA].includes(itemType);
60
+ };
61
+ exports.isErc721Item = isErc721Item;
62
+ var isErc1155Item = function (itemType) {
63
+ return [constants_1.ItemType.ERC1155, constants_1.ItemType.ERC1155_WITH_CRITERIA].includes(itemType);
64
+ };
65
+ exports.isErc1155Item = isErc1155Item;
66
+ var isCriteriaItem = function (itemType) {
67
+ return [constants_1.ItemType.ERC721_WITH_CRITERIA, constants_1.ItemType.ERC1155_WITH_CRITERIA].includes(itemType);
68
+ };
69
+ exports.isCriteriaItem = isCriteriaItem;
70
+ var getPresentItemAmount = function (_a) {
71
+ var startAmount = _a.startAmount, endAmount = _a.endAmount, timeBasedItemParams = _a.timeBasedItemParams;
72
+ var startAmountBn = ethers_1.BigNumber.from(startAmount);
73
+ var endAmountBn = ethers_1.BigNumber.from(endAmount);
74
+ if (!timeBasedItemParams) {
75
+ return startAmountBn.gt(endAmountBn) ? startAmountBn : endAmountBn;
76
+ }
77
+ var isConsiderationItem = timeBasedItemParams.isConsiderationItem, currentBlockTimestamp = timeBasedItemParams.currentBlockTimestamp, ascendingAmountTimestampBuffer = timeBasedItemParams.ascendingAmountTimestampBuffer, startTime = timeBasedItemParams.startTime, endTime = timeBasedItemParams.endTime;
78
+ var duration = ethers_1.BigNumber.from(endTime).sub(startTime);
79
+ var isAscending = endAmountBn.gt(startAmount);
80
+ var adjustedBlockTimestamp = ethers_1.BigNumber.from(isAscending
81
+ ? currentBlockTimestamp + ascendingAmountTimestampBuffer
82
+ : currentBlockTimestamp);
83
+ if (adjustedBlockTimestamp.lt(startTime)) {
84
+ return startAmountBn;
85
+ }
86
+ var elapsed = (adjustedBlockTimestamp.gt(endTime)
87
+ ? ethers_1.BigNumber.from(endTime)
88
+ : adjustedBlockTimestamp).sub(startTime);
89
+ var remaining = duration.sub(elapsed);
90
+ // Adjust amounts based on current time
91
+ // For offer items, we round down
92
+ // For consideration items, we round up
93
+ return startAmountBn
94
+ .mul(remaining)
95
+ .add(endAmountBn.mul(elapsed))
96
+ .add(isConsiderationItem ? duration.sub(1) : 0)
97
+ .div(duration);
98
+ };
99
+ exports.getPresentItemAmount = getPresentItemAmount;
100
+ var getSummedTokenAndIdentifierAmounts = function (_a) {
101
+ var items = _a.items, criterias = _a.criterias, timeBasedItemParams = _a.timeBasedItemParams;
102
+ var itemToCriteria = (0, criteria_1.getItemToCriteriaMap)(items, criterias);
103
+ var tokenAndIdentifierToSummedAmount = items.reduce(function (map, item) {
104
+ var _a, _b;
105
+ var _c, _d, _e, _f;
106
+ var identifierOrCriteria = (_d = (_c = itemToCriteria.get(item)) === null || _c === void 0 ? void 0 : _c.identifier) !== null && _d !== void 0 ? _d : item.identifierOrCriteria;
107
+ return __assign(__assign({}, map), (_a = {}, _a[item.token] = __assign(__assign({}, map[item.token]), (_b = {}, _b[identifierOrCriteria] = ((_f = (_e = map[item.token]) === null || _e === void 0 ? void 0 : _e[identifierOrCriteria]) !== null && _f !== void 0 ? _f : ethers_1.BigNumber.from(0)).add((0, exports.getPresentItemAmount)({
108
+ startAmount: item.startAmount,
109
+ endAmount: item.endAmount,
110
+ timeBasedItemParams: timeBasedItemParams,
111
+ })), _b)), _a));
112
+ }, {});
113
+ return tokenAndIdentifierToSummedAmount;
114
+ };
115
+ exports.getSummedTokenAndIdentifierAmounts = getSummedTokenAndIdentifierAmounts;
116
+ /**
117
+ * Returns the maximum size of units possible for the order
118
+ * If any of the items on a partially fillable order specify a different "startAmount" and "endAmount
119
+ * (e.g. they are ascending-amount or descending-amount items), the fraction will be applied to both amounts
120
+ * prior to determining the current price. This ensures that cleanly divisible amounts can be chosen when
121
+ * constructing the order without a dependency on the time when the order is ultimately fulfilled.
122
+ */
123
+ var getMaximumSizeForOrder = function (_a) {
124
+ var _b = _a.parameters, offer = _b.offer, consideration = _b.consideration;
125
+ var allItems = __spreadArray(__spreadArray([], __read(offer), false), __read(consideration), false);
126
+ var amounts = allItems.flatMap(function (_a) {
127
+ var startAmount = _a.startAmount, endAmount = _a.endAmount;
128
+ return [
129
+ startAmount,
130
+ endAmount,
131
+ ];
132
+ });
133
+ return (0, gcd_1.findGcd)(amounts);
134
+ };
135
+ exports.getMaximumSizeForOrder = getMaximumSizeForOrder;
136
+ //# sourceMappingURL=item.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"item.js","sourceRoot":"","sources":["../../src/utils/item.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /** Giant TODO for match orders
2
+ # Match orders
3
+
4
+ - Format: list of fulfillments
5
+ - Each fulfillment represents a single transfer or “execution”
6
+ - Each fulfillment specifies an array of offer “components” corresponding to offer items to spend as well as an array of consideration “components” corresponding to consideration items to receive
7
+ - every offer component and consideration component contains an index of the order it is from as well as an index of the item in the respective offer or consideration array on that order
8
+ - the “from” address will be the offerer of whatever offer items are being spent
9
+ - the “to” address will be the recipient of whatever consideration items are being received
10
+ - the “One rule” to follow for the whole set of fulfillments:
11
+ - All consideration items must be fully accounted for after adjusting for partial fills and ascending/descending amounts
12
+ - the “Four rules” to follow for each distinct fulfillment:
13
+ 1. you need at least one offer component and at least one consideration component for each fulfillment; otherwise you don’t know what the “from” or “to” address should be
14
+ 2. the offer item corresponding to the first offer component has to match the consideration item corresponding to the first consideration component (with the exception of the amount); otherwise you’re not sending the item that the recipient is expecting
15
+ 3. any additional offer items need to match the original offer items (with the exception of the amount) and the same *the offerer*; otherwise you’re composing different items or different origins.
16
+ 1. This implies that ERC721 fulfillments will always have a single offer component (even if that corresponding offer item is present in multiple fulfillments, i.e. criteria-based partial fills)
17
+
18
+ Example: Bulk purchase
19
+
20
+ - Five distinct sellers create orders to sell ERC721 NFTs for ETH.
21
+ - single offer item on each order: the NFT
22
+ - two consideration items on each order: 10 ETH to the offerer and 1 ETH to OpenSea
23
+ - order index 1 through 5
24
+ - To fulfill this, fulfiller creates a *sixth* order to buy all 5 NFTs for ETH
25
+ - single offer item: 55 ETH or `(10 + 1) * 5`
26
+ - five consideration items: all five NFTs
27
+ - order index 0 (by convention)
28
+ - This order requires exactly 11 transfers or executions (assuming 5 distinct sellers), translating to 11 fulfillments:
29
+ - 5 transfers of 10 ETH each from order 0 offerer (i.e. fulfiller) to order 1-5 offerers
30
+ - These fulfillments will have a single offer component and single consideration component (offer component: order 0 index 0 and consideration component: orders 1-5 index 0)
31
+ - 5 transfers of 1 NFT each from order 1-5 offers to order 0 offerer (i.e. fulfiller)
32
+ - These fulfillments will have a single offer component and single fulfillment component (offer component: orders 1-5 index 0 and consideration component order 0 index 0-4)
33
+ - 1 transfer of 5 ETH from order 0 offerer (i.e. fulfiller) to OpenSea
34
+ - This fulfillment will have a single offer component mapping to order index 0 + item index 0, but *five* consideration components mapping to order index 1-5 + item index 1
35
+
36
+ The algorithm (broad-strokes first pass)
37
+
38
+ 1. Take all the orders you want to fulfill and retrieve the latest amounts for those orders based on amount filled, amount *desired* to fill, and ascending/descending amounts (include sufficient buffer on those)
39
+ 2. “flatten” those orders into:
40
+ - all the offer items (and include the order index, item index, and offerer alongside the item)
41
+ - all the consideration items (and include the order index and item index alongside the item; the recipient is already on the consideration items)
42
+ 3. Aggregate those items by type + token + identifier + (offerer / recipient), summing up all the amounts (we do need to track the original amounts as well here)
43
+ 4. Quickly check to see if there are any aggregated offer items with the same type + token + identifier + offerer as an aggregated consideration item’s type + token + identifier + recipient (i.e. offerer == recipient) — if so, create a fulfillment for those and decrement both (no execution / transfer will be created for these fulfillments)
44
+ 5. Retrieve all approvals and balances for each aggregated offer item; increment / decrement them as we go and ensure they never go below zero
45
+ 6. Search for fulfillments that can already be performed before the fulfiller’s order has even been created; if any exist, generate those fulfillments first (the goal is to reduce the number of items on the fulfiller’s order).
46
+ - To generate a fulfillment, subtract whatever is lower between the aggregated offer and aggregated consideration it is being matched with from both and register the fulfillment.
47
+ - There will likely be some combination that optimizes for total number of transfers; see if these can be optimized.
48
+ - By way of example, say a fulfiller is accepting offers to sell multiple NFTs at once, and the aggregate fees owed to OpenSea are exactly 1 WETH and it so happens that one of the NFTS has an offer for exactly 1 WETH — that offerer should pay the fees for all the orders being fulfilled in a single transaction.
49
+ - Repeat this process until the fulfillments cannot be compressed any further.
50
+ 7. Then, create the mirror order with an offer item for each remaining (aggregated) consideration item and a consideration item for each remaining (aggregated) offer item; check for sufficient approval on each derived offer item
51
+ 8. Run the same sequence as from in step 6, but include the last order as well
52
+ 9. Ensure that all consideration items have been met!
53
+ */
54
+ export {};
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ /** Giant TODO for match orders
3
+ # Match orders
4
+
5
+ - Format: list of fulfillments
6
+ - Each fulfillment represents a single transfer or “execution”
7
+ - Each fulfillment specifies an array of offer “components” corresponding to offer items to spend as well as an array of consideration “components” corresponding to consideration items to receive
8
+ - every offer component and consideration component contains an index of the order it is from as well as an index of the item in the respective offer or consideration array on that order
9
+ - the “from” address will be the offerer of whatever offer items are being spent
10
+ - the “to” address will be the recipient of whatever consideration items are being received
11
+ - the “One rule” to follow for the whole set of fulfillments:
12
+ - All consideration items must be fully accounted for after adjusting for partial fills and ascending/descending amounts
13
+ - the “Four rules” to follow for each distinct fulfillment:
14
+ 1. you need at least one offer component and at least one consideration component for each fulfillment; otherwise you don’t know what the “from” or “to” address should be
15
+ 2. the offer item corresponding to the first offer component has to match the consideration item corresponding to the first consideration component (with the exception of the amount); otherwise you’re not sending the item that the recipient is expecting
16
+ 3. any additional offer items need to match the original offer items (with the exception of the amount) and the same *the offerer*; otherwise you’re composing different items or different origins.
17
+ 1. This implies that ERC721 fulfillments will always have a single offer component (even if that corresponding offer item is present in multiple fulfillments, i.e. criteria-based partial fills)
18
+
19
+ Example: Bulk purchase
20
+
21
+ - Five distinct sellers create orders to sell ERC721 NFTs for ETH.
22
+ - single offer item on each order: the NFT
23
+ - two consideration items on each order: 10 ETH to the offerer and 1 ETH to OpenSea
24
+ - order index 1 through 5
25
+ - To fulfill this, fulfiller creates a *sixth* order to buy all 5 NFTs for ETH
26
+ - single offer item: 55 ETH or `(10 + 1) * 5`
27
+ - five consideration items: all five NFTs
28
+ - order index 0 (by convention)
29
+ - This order requires exactly 11 transfers or executions (assuming 5 distinct sellers), translating to 11 fulfillments:
30
+ - 5 transfers of 10 ETH each from order 0 offerer (i.e. fulfiller) to order 1-5 offerers
31
+ - These fulfillments will have a single offer component and single consideration component (offer component: order 0 index 0 and consideration component: orders 1-5 index 0)
32
+ - 5 transfers of 1 NFT each from order 1-5 offers to order 0 offerer (i.e. fulfiller)
33
+ - These fulfillments will have a single offer component and single fulfillment component (offer component: orders 1-5 index 0 and consideration component order 0 index 0-4)
34
+ - 1 transfer of 5 ETH from order 0 offerer (i.e. fulfiller) to OpenSea
35
+ - This fulfillment will have a single offer component mapping to order index 0 + item index 0, but *five* consideration components mapping to order index 1-5 + item index 1
36
+
37
+ The algorithm (broad-strokes first pass)
38
+
39
+ 1. Take all the orders you want to fulfill and retrieve the latest amounts for those orders based on amount filled, amount *desired* to fill, and ascending/descending amounts (include sufficient buffer on those)
40
+ 2. “flatten” those orders into:
41
+ - all the offer items (and include the order index, item index, and offerer alongside the item)
42
+ - all the consideration items (and include the order index and item index alongside the item; the recipient is already on the consideration items)
43
+ 3. Aggregate those items by type + token + identifier + (offerer / recipient), summing up all the amounts (we do need to track the original amounts as well here)
44
+ 4. Quickly check to see if there are any aggregated offer items with the same type + token + identifier + offerer as an aggregated consideration item’s type + token + identifier + recipient (i.e. offerer == recipient) — if so, create a fulfillment for those and decrement both (no execution / transfer will be created for these fulfillments)
45
+ 5. Retrieve all approvals and balances for each aggregated offer item; increment / decrement them as we go and ensure they never go below zero
46
+ 6. Search for fulfillments that can already be performed before the fulfiller’s order has even been created; if any exist, generate those fulfillments first (the goal is to reduce the number of items on the fulfiller’s order).
47
+ - To generate a fulfillment, subtract whatever is lower between the aggregated offer and aggregated consideration it is being matched with from both and register the fulfillment.
48
+ - There will likely be some combination that optimizes for total number of transfers; see if these can be optimized.
49
+ - By way of example, say a fulfiller is accepting offers to sell multiple NFTs at once, and the aggregate fees owed to OpenSea are exactly 1 WETH and it so happens that one of the NFTS has an offer for exactly 1 WETH — that offerer should pay the fees for all the orders being fulfilled in a single transaction.
50
+ - Repeat this process until the fulfillments cannot be compressed any further.
51
+ 7. Then, create the mirror order with an offer item for each remaining (aggregated) consideration item and a consideration item for each remaining (aggregated) offer item; check for sufficient approval on each derived offer item
52
+ 8. Run the same sequence as from in step 6, but include the last order as well
53
+ 9. Ensure that all consideration items have been met!
54
+ */
55
+ Object.defineProperty(exports, "__esModule", { value: true });
56
+ //# sourceMappingURL=match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match.js","sourceRoot":"","sources":["../../src/utils/match.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAoDI"}
@@ -0,0 +1,11 @@
1
+ import MerkleTreeJS from "merkletreejs";
2
+ /**
3
+ * Simple wrapper over the MerkleTree in merkletreejs.
4
+ * Handles hashing identifiers to be compatible with Seaport.
5
+ */
6
+ export declare class MerkleTree {
7
+ tree: MerkleTreeJS;
8
+ constructor(identifiers: string[]);
9
+ getProof(identifier: string): string[];
10
+ getRoot(): string;
11
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MerkleTree = void 0;
7
+ var ethers_1 = require("ethers");
8
+ var utils_1 = require("ethers/lib/utils");
9
+ var merkletreejs_1 = __importDefault(require("merkletreejs"));
10
+ var hashIdentifier = function (identifier) {
11
+ return (0, utils_1.keccak256)(Buffer.from(ethers_1.BigNumber.from(identifier).toHexString().slice(2).padStart(64, "0"), "hex"));
12
+ };
13
+ /**
14
+ * Simple wrapper over the MerkleTree in merkletreejs.
15
+ * Handles hashing identifiers to be compatible with Seaport.
16
+ */
17
+ var MerkleTree = /** @class */ (function () {
18
+ function MerkleTree(identifiers) {
19
+ this.tree = new merkletreejs_1.default(identifiers.map(hashIdentifier), utils_1.keccak256, {
20
+ sort: true,
21
+ });
22
+ }
23
+ MerkleTree.prototype.getProof = function (identifier) {
24
+ return this.tree.getHexProof(hashIdentifier(identifier));
25
+ };
26
+ MerkleTree.prototype.getRoot = function () {
27
+ return this.tree.getRoot().toString("hex") ? this.tree.getHexRoot() : "0";
28
+ };
29
+ return MerkleTree;
30
+ }());
31
+ exports.MerkleTree = MerkleTree;
32
+ //# sourceMappingURL=merkletree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkletree.js","sourceRoot":"","sources":["../../src/utils/merkletree.ts"],"names":[],"mappings":";;;;;;AAAA,iCAAmC;AACnC,0CAA6C;AAC7C,8DAAwC;AAExC,IAAM,cAAc,GAAG,UAAC,UAAkB;IACxC,OAAA,IAAA,iBAAS,EACP,MAAM,CAAC,IAAI,CACT,kBAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,EACnE,KAAK,CACN,CACF;AALD,CAKC,CAAC;AAEJ;;;GAGG;AACH;IAGE,oBAAY,WAAqB;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,sBAAY,CAAC,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,iBAAS,EAAE;YACvE,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;IACL,CAAC;IAED,6BAAQ,GAAR,UAAS,UAAkB;QACzB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED,4BAAO,GAAP;QACE,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IAC5E,CAAC;IACH,iBAAC;AAAD,CAAC,AAhBD,IAgBC;AAhBY,gCAAU"}
@@ -0,0 +1,37 @@
1
+ import { BigNumber, BigNumberish } from "ethers";
2
+ import type { ConsiderationItem, CreateInputItem, Fee, Item, OfferItem, Order, OrderParameters } from "../types";
3
+ export declare const feeToConsiderationItem: ({ fee, token, baseAmount, baseEndAmount, }: {
4
+ fee: Fee;
5
+ token: string;
6
+ baseAmount: BigNumberish;
7
+ baseEndAmount?: BigNumberish | undefined;
8
+ }) => ConsiderationItem;
9
+ export declare const deductFees: <T extends Item>(items: T[], fees?: readonly Fee[] | undefined) => T[];
10
+ export declare const mapInputItemToOfferItem: (item: CreateInputItem) => OfferItem;
11
+ export declare const areAllCurrenciesSame: ({ offer, consideration, }: Pick<OrderParameters, "offer" | "consideration">) => boolean;
12
+ export declare const totalItemsAmount: <T extends OfferItem>(items: T[]) => {
13
+ startAmount: BigNumber;
14
+ endAmount: BigNumber;
15
+ };
16
+ /**
17
+ * Maps order offer and consideration item amounts based on the order's filled status
18
+ * After applying the fraction, we can view this order as the "canonical" order for which we
19
+ * check approvals and balances
20
+ */
21
+ export declare const mapOrderAmountsFromFilledStatus: (order: Order, { totalFilled, totalSize }: {
22
+ totalFilled: BigNumber;
23
+ totalSize: BigNumber;
24
+ }) => Order;
25
+ /**
26
+ * Maps order offer and consideration item amounts based on the units needed to fulfill
27
+ * After applying the fraction, we can view this order as the "canonical" order for which we
28
+ * check approvals and balances
29
+ * Returns the numerator and denominator as well, converting this to an AdvancedOrder
30
+ */
31
+ export declare const mapOrderAmountsFromUnitsToFill: (order: Order, { unitsToFill, totalFilled, totalSize, }: {
32
+ unitsToFill: BigNumberish;
33
+ totalFilled: BigNumber;
34
+ totalSize: BigNumber;
35
+ }) => Order;
36
+ export declare const generateRandomSalt: () => string;
37
+ export declare const shouldUseMatchForFulfill: () => boolean;
@@ -0,0 +1,224 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __read = (this && this.__read) || function (o, n) {
14
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
15
+ if (!m) return o;
16
+ var i = m.call(o), r, ar = [], e;
17
+ try {
18
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
19
+ }
20
+ catch (error) { e = { error: error }; }
21
+ finally {
22
+ try {
23
+ if (r && !r.done && (m = i["return"])) m.call(i);
24
+ }
25
+ finally { if (e) throw e.error; }
26
+ }
27
+ return ar;
28
+ };
29
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
30
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
31
+ if (ar || !(i in from)) {
32
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
33
+ ar[i] = from[i];
34
+ }
35
+ }
36
+ return to.concat(ar || Array.prototype.slice.call(from));
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.shouldUseMatchForFulfill = exports.generateRandomSalt = exports.mapOrderAmountsFromUnitsToFill = exports.mapOrderAmountsFromFilledStatus = exports.totalItemsAmount = exports.areAllCurrenciesSame = exports.mapInputItemToOfferItem = exports.deductFees = exports.feeToConsiderationItem = void 0;
40
+ var ethers_1 = require("ethers");
41
+ var constants_1 = require("../constants");
42
+ var item_1 = require("./item");
43
+ var merkletree_1 = require("./merkletree");
44
+ var multiplyBasisPoints = function (amount, basisPoints) {
45
+ return ethers_1.BigNumber.from(amount)
46
+ .mul(ethers_1.BigNumber.from(basisPoints))
47
+ .div(constants_1.ONE_HUNDRED_PERCENT_BP);
48
+ };
49
+ var feeToConsiderationItem = function (_a) {
50
+ var fee = _a.fee, token = _a.token, baseAmount = _a.baseAmount, _b = _a.baseEndAmount, baseEndAmount = _b === void 0 ? baseAmount : _b;
51
+ return {
52
+ itemType: token === ethers_1.ethers.constants.AddressZero ? constants_1.ItemType.NATIVE : constants_1.ItemType.ERC20,
53
+ token: token,
54
+ identifierOrCriteria: "0",
55
+ startAmount: multiplyBasisPoints(baseAmount, fee.basisPoints).toString(),
56
+ endAmount: multiplyBasisPoints(baseEndAmount, fee.basisPoints).toString(),
57
+ recipient: fee.recipient,
58
+ };
59
+ };
60
+ exports.feeToConsiderationItem = feeToConsiderationItem;
61
+ var deductFees = function (items, fees) {
62
+ if (!fees) {
63
+ return items;
64
+ }
65
+ var totalBasisPoints = fees.reduce(function (accBasisPoints, fee) { return accBasisPoints + fee.basisPoints; }, 0);
66
+ return items.map(function (item) { return (__assign(__assign({}, item), { startAmount: (0, item_1.isCurrencyItem)(item)
67
+ ? ethers_1.BigNumber.from(item.startAmount)
68
+ .sub(multiplyBasisPoints(item.startAmount, totalBasisPoints))
69
+ .toString()
70
+ : item.startAmount, endAmount: (0, item_1.isCurrencyItem)(item)
71
+ ? ethers_1.BigNumber.from(item.endAmount)
72
+ .sub(multiplyBasisPoints(item.endAmount, totalBasisPoints))
73
+ .toString()
74
+ : item.endAmount })); });
75
+ };
76
+ exports.deductFees = deductFees;
77
+ var mapInputItemToOfferItem = function (item) {
78
+ var _a, _b, _c, _d, _e, _f, _g;
79
+ // Item is an NFT
80
+ if ("itemType" in item) {
81
+ // Convert this to a criteria based item
82
+ if ("identifiers" in item) {
83
+ var tree = new merkletree_1.MerkleTree(item.identifiers);
84
+ return {
85
+ itemType: item.itemType === constants_1.ItemType.ERC721
86
+ ? constants_1.ItemType.ERC721_WITH_CRITERIA
87
+ : constants_1.ItemType.ERC1155_WITH_CRITERIA,
88
+ token: item.token,
89
+ identifierOrCriteria: tree.getRoot(),
90
+ startAmount: (_a = item.amount) !== null && _a !== void 0 ? _a : "1",
91
+ endAmount: (_c = (_b = item.endAmount) !== null && _b !== void 0 ? _b : item.amount) !== null && _c !== void 0 ? _c : "1",
92
+ };
93
+ }
94
+ if ("amount" in item || "endAmount" in item) {
95
+ return {
96
+ itemType: item.itemType,
97
+ token: item.token,
98
+ identifierOrCriteria: item.identifier,
99
+ startAmount: item.amount,
100
+ endAmount: (_e = (_d = item.endAmount) !== null && _d !== void 0 ? _d : item.amount) !== null && _e !== void 0 ? _e : "1",
101
+ };
102
+ }
103
+ return {
104
+ itemType: item.itemType,
105
+ token: item.token,
106
+ identifierOrCriteria: item.identifier,
107
+ startAmount: "1",
108
+ endAmount: "1",
109
+ };
110
+ }
111
+ // Item is a currency
112
+ return {
113
+ itemType: item.token && item.token !== ethers_1.ethers.constants.AddressZero
114
+ ? constants_1.ItemType.ERC20
115
+ : constants_1.ItemType.NATIVE,
116
+ token: (_f = item.token) !== null && _f !== void 0 ? _f : ethers_1.ethers.constants.AddressZero,
117
+ identifierOrCriteria: "0",
118
+ startAmount: item.amount,
119
+ endAmount: (_g = item.endAmount) !== null && _g !== void 0 ? _g : item.amount,
120
+ };
121
+ };
122
+ exports.mapInputItemToOfferItem = mapInputItemToOfferItem;
123
+ var areAllCurrenciesSame = function (_a) {
124
+ var offer = _a.offer, consideration = _a.consideration;
125
+ var allItems = __spreadArray(__spreadArray([], __read(offer), false), __read(consideration), false);
126
+ var currencies = allItems.filter(item_1.isCurrencyItem);
127
+ return currencies.every(function (_a) {
128
+ var itemType = _a.itemType, token = _a.token;
129
+ return itemType === currencies[0].itemType &&
130
+ token.toLowerCase() === currencies[0].token.toLowerCase();
131
+ });
132
+ };
133
+ exports.areAllCurrenciesSame = areAllCurrenciesSame;
134
+ var totalItemsAmount = function (items) {
135
+ var initialValues = {
136
+ startAmount: ethers_1.BigNumber.from(0),
137
+ endAmount: ethers_1.BigNumber.from(0),
138
+ };
139
+ return items
140
+ .map(function (_a) {
141
+ var startAmount = _a.startAmount, endAmount = _a.endAmount;
142
+ return ({
143
+ startAmount: startAmount,
144
+ endAmount: endAmount,
145
+ });
146
+ })
147
+ .reduce(function (_a, _b) {
148
+ var totalStartAmount = _a.startAmount, totalEndAmount = _a.endAmount;
149
+ var startAmount = _b.startAmount, endAmount = _b.endAmount;
150
+ return ({
151
+ startAmount: totalStartAmount.add(startAmount),
152
+ endAmount: totalEndAmount.add(endAmount),
153
+ });
154
+ }, {
155
+ startAmount: ethers_1.BigNumber.from(0),
156
+ endAmount: ethers_1.BigNumber.from(0),
157
+ });
158
+ };
159
+ exports.totalItemsAmount = totalItemsAmount;
160
+ /**
161
+ * Maps order offer and consideration item amounts based on the order's filled status
162
+ * After applying the fraction, we can view this order as the "canonical" order for which we
163
+ * check approvals and balances
164
+ */
165
+ var mapOrderAmountsFromFilledStatus = function (order, _a) {
166
+ var totalFilled = _a.totalFilled, totalSize = _a.totalSize;
167
+ if (totalFilled.eq(0) || totalSize.eq(0)) {
168
+ return order;
169
+ }
170
+ // i.e if totalFilled is 3 and totalSize is 4, there are 1 / 4 order amounts left to fill.
171
+ var basisPoints = totalSize
172
+ .sub(totalFilled)
173
+ .mul(constants_1.ONE_HUNDRED_PERCENT_BP)
174
+ .div(totalSize);
175
+ return {
176
+ parameters: __assign(__assign({}, order.parameters), { offer: order.parameters.offer.map(function (item) { return (__assign(__assign({}, item), { startAmount: multiplyBasisPoints(item.startAmount, basisPoints).toString(), endAmount: multiplyBasisPoints(item.endAmount, basisPoints).toString() })); }), consideration: order.parameters.consideration.map(function (item) { return (__assign(__assign({}, item), { startAmount: multiplyBasisPoints(item.startAmount, basisPoints).toString(), endAmount: multiplyBasisPoints(item.endAmount, basisPoints).toString() })); }) }),
177
+ signature: order.signature,
178
+ };
179
+ };
180
+ exports.mapOrderAmountsFromFilledStatus = mapOrderAmountsFromFilledStatus;
181
+ /**
182
+ * Maps order offer and consideration item amounts based on the units needed to fulfill
183
+ * After applying the fraction, we can view this order as the "canonical" order for which we
184
+ * check approvals and balances
185
+ * Returns the numerator and denominator as well, converting this to an AdvancedOrder
186
+ */
187
+ var mapOrderAmountsFromUnitsToFill = function (order, _a) {
188
+ var unitsToFill = _a.unitsToFill, totalFilled = _a.totalFilled, totalSize = _a.totalSize;
189
+ var unitsToFillBn = ethers_1.BigNumber.from(unitsToFill);
190
+ if (unitsToFillBn.lte(0)) {
191
+ throw new Error("Units to fill must be greater than 1");
192
+ }
193
+ var maxUnits = (0, item_1.getMaximumSizeForOrder)(order);
194
+ if (totalSize.eq(0)) {
195
+ totalSize = maxUnits;
196
+ }
197
+ // This is the percentage of the order that is left to be fulfilled, and therefore we can't fill more than that.
198
+ var remainingOrderPercentageToBeFilled = totalSize
199
+ .sub(totalFilled)
200
+ .mul(constants_1.ONE_HUNDRED_PERCENT_BP)
201
+ .div(totalSize);
202
+ // i.e if totalSize is 8 and unitsToFill is 3, then we multiply every amount by 3 / 8
203
+ var unitsToFillBasisPoints = unitsToFillBn
204
+ .mul(constants_1.ONE_HUNDRED_PERCENT_BP)
205
+ .div(maxUnits);
206
+ // We basically choose the lesser between the units requested to be filled and the actual remaining order amount left
207
+ // This is so that if a user tries to fulfill an order that is 1/2 filled, and supplies a fraction such as 3/4, the maximum
208
+ // amount to fulfill is 1/2 instead of 3/4
209
+ var basisPoints = remainingOrderPercentageToBeFilled.gt(unitsToFillBasisPoints)
210
+ ? unitsToFillBasisPoints
211
+ : remainingOrderPercentageToBeFilled;
212
+ return {
213
+ parameters: __assign(__assign({}, order.parameters), { offer: order.parameters.offer.map(function (item) { return (__assign(__assign({}, item), { startAmount: multiplyBasisPoints(item.startAmount, basisPoints).toString(), endAmount: multiplyBasisPoints(item.endAmount, basisPoints).toString() })); }), consideration: order.parameters.consideration.map(function (item) { return (__assign(__assign({}, item), { startAmount: multiplyBasisPoints(item.startAmount, basisPoints).toString(), endAmount: multiplyBasisPoints(item.endAmount, basisPoints).toString() })); }) }),
214
+ signature: order.signature,
215
+ };
216
+ };
217
+ exports.mapOrderAmountsFromUnitsToFill = mapOrderAmountsFromUnitsToFill;
218
+ var generateRandomSalt = function () {
219
+ return "0x".concat(Buffer.from(ethers_1.ethers.utils.randomBytes(16)).toString("hex"));
220
+ };
221
+ exports.generateRandomSalt = generateRandomSalt;
222
+ var shouldUseMatchForFulfill = function () { return true; };
223
+ exports.shouldUseMatchForFulfill = shouldUseMatchForFulfill;
224
+ //# sourceMappingURL=order.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"order.js","sourceRoot":"","sources":["../../src/utils/order.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Contract } from "ethers";
2
+ import { CreateOrderAction, ExchangeAction, OrderUseCase, TransactionMethods, ContractMethodReturnType } from "../types";
3
+ export declare const executeAllActions: <T extends CreateOrderAction | ExchangeAction<unknown>>(actions: T extends CreateOrderAction ? import("../types").CreateOrderActions : import("../types").OrderExchangeActions<T extends ExchangeAction<infer U> ? U : never>) => Promise<import("ethers").ContractTransaction | import("../types").OrderWithCounter>;
4
+ export declare const getTransactionMethods: <T extends Contract, U extends keyof T["functions"]>(contract: T, method: U, args: Parameters<T["functions"][U]>) => TransactionMethods<Awaited<ReturnType<T["callStatic"][U]>>>;