@zero-tech/zauction-sdk 0.2.10 → 0.2.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. package/package.json +3 -2
  2. package/src/actions/acceptBid.ts +167 -0
  3. package/src/actions/approveDomainTransfer.ts +25 -0
  4. package/src/actions/approveSpender.ts +27 -0
  5. package/src/actions/buyNow.ts +109 -0
  6. package/src/actions/cancelBid.ts +37 -0
  7. package/src/actions/getBuyNowListing.ts +65 -0
  8. package/src/actions/getPaymentTokenAllowance.ts +30 -0
  9. package/src/actions/index.ts +11 -0
  10. package/src/actions/isZAuctionApproved.ts +20 -0
  11. package/src/actions/placeBid.ts +102 -0
  12. package/src/actions/setBuyNowPrice.ts +56 -0
  13. package/src/actions/setNetworkPaymentToken.ts +46 -0
  14. package/src/api/actions/encodeBid.ts +44 -0
  15. package/src/api/actions/encodeCancelMessage.ts +24 -0
  16. package/src/api/actions/helpers.ts +61 -0
  17. package/src/api/actions/index.ts +6 -0
  18. package/src/api/actions/listBidsForAccount.ts +24 -0
  19. package/src/api/actions/listBidsForTokens.ts +39 -0
  20. package/src/api/actions/submitBid.ts +28 -0
  21. package/src/api/actions/submitCancelMessage.ts +30 -0
  22. package/src/api/client.ts +78 -0
  23. package/src/api/index.ts +1 -0
  24. package/src/api/types.ts +47 -0
  25. package/src/contracts/index.ts +53 -0
  26. package/src/contracts/types/IERC20.d.ts +294 -0
  27. package/src/contracts/types/IERC721.d.ts +472 -0
  28. package/src/contracts/types/IZNSHub.d.ts +578 -0
  29. package/src/contracts/types/ZAuction.d.ts +1487 -0
  30. package/src/contracts/types/ZAuctionV1.d.ts +440 -0
  31. package/src/contracts/types/commons.ts +36 -0
  32. package/src/contracts/types/factories/IERC20__factory.ts +203 -0
  33. package/src/contracts/types/factories/IERC721__factory.ts +308 -0
  34. package/src/contracts/types/factories/IZNSHub__factory.ts +311 -0
  35. package/src/contracts/types/factories/ZAuctionV1__factory.ts +326 -0
  36. package/src/contracts/types/factories/ZAuction__factory.ts +1033 -0
  37. package/src/contracts/types/index.ts +14 -0
  38. package/src/index.ts +468 -0
  39. package/src/subgraph/actions/index.ts +4 -0
  40. package/src/subgraph/actions/listAllBuyNowListings.ts +69 -0
  41. package/src/subgraph/actions/listAllSales.ts +57 -0
  42. package/src/subgraph/actions/listBuyNowSales.ts +44 -0
  43. package/src/subgraph/actions/listSales.ts +33 -0
  44. package/src/subgraph/client.ts +62 -0
  45. package/src/subgraph/helpers/index.ts +39 -0
  46. package/src/subgraph/index.ts +1 -0
  47. package/src/subgraph/queries.ts +75 -0
  48. package/src/subgraph/types.ts +58 -0
  49. package/src/types.ts +181 -0
  50. package/src/utilities/index.ts +2 -0
  51. package/src/utilities/logging.ts +27 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zero-tech/zauction-sdk",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "repository": "git@github.com:zer0-os/zAuction-SDK.git",
@@ -10,7 +10,8 @@
10
10
  "yarn": ">=1.15.2"
11
11
  },
12
12
  "files": [
13
- "lib/"
13
+ "lib/",
14
+ "src/"
14
15
  ],
15
16
  "scripts": {
16
17
  "build": "tsc --build --verbose ./tsconfig.build.json",
@@ -0,0 +1,167 @@
1
+ import { ethers } from "ethers";
2
+ import {
3
+ getERC721Contract,
4
+ getZAuctionContract,
5
+ getZAuctionV1Contract,
6
+ getZnsHubContract,
7
+ } from "../contracts";
8
+ import { IERC721, IZNSHub, ZAuction, ZAuctionV1 } from "../contracts/types";
9
+ import { Bid, Config } from "../types";
10
+ import { getLogger } from "../utilities";
11
+
12
+ const logger = getLogger("actions:acceptBid");
13
+
14
+ const verifyAccount = async (
15
+ zAuction: ZAuction | ZAuctionV1,
16
+ data: string,
17
+ signedMessage: string,
18
+ bidder: string
19
+ ): Promise<void> => {
20
+ const unsignedMessage = await zAuction.toEthSignedMessageHash(
21
+ ethers.utils.arrayify(data)
22
+ );
23
+
24
+ const recoveredAccount = await zAuction.recover(
25
+ unsignedMessage,
26
+ signedMessage
27
+ );
28
+
29
+ if (recoveredAccount !== bidder) {
30
+ throw Error("Recovered incorrect account");
31
+ }
32
+ };
33
+
34
+ // Accept a bid for a domain, supporting legacy bids
35
+ export const acceptBid = async (
36
+ bid: Bid,
37
+ signer: ethers.Signer,
38
+ config: Config
39
+ ): Promise<ethers.ContractTransaction> => {
40
+ logger.trace(
41
+ `Calling to accept a bid by user ${bid.bidder} with bidNonce of ${bid.bidNonce}`
42
+ );
43
+
44
+ // If not explicitly v2 bid, then assume v1
45
+ const isVersion2 = bid.version === "2.0";
46
+
47
+ // route to legacy if version 1.0
48
+ const zAuctionAddress = isVersion2
49
+ ? config.zAuctionAddress
50
+ : config.zAuctionLegacyAddress;
51
+
52
+ const hub: IZNSHub = await getZnsHubContract(signer, config.znsHubAddress);
53
+ const domainContract = await hub.getRegistrarForDomain(bid.tokenId);
54
+ const nftContract: IERC721 = await getERC721Contract(signer, domainContract);
55
+
56
+ const owner = await nftContract.ownerOf(bid.tokenId);
57
+ const signerAddress = await signer.getAddress();
58
+
59
+ if (owner !== signerAddress) {
60
+ throw Error("Cannot accept a bid for a domain that is not yours");
61
+ }
62
+ if (owner === bid.bidder) {
63
+ throw Error("Cannot sell to self");
64
+ }
65
+
66
+ if (isVersion2) {
67
+ const zAuction: ZAuction = await getZAuctionContract(
68
+ signer,
69
+ zAuctionAddress
70
+ );
71
+
72
+ if (bid.bidToken) {
73
+ // v2.1 bid
74
+ logger.trace(
75
+ `v2.1 Bid: Payment token for domain ${bid.tokenId} is ${bid.bidToken}`
76
+ );
77
+
78
+ const data = await zAuction.createBidV2(
79
+ bid.bidNonce,
80
+ bid.amount,
81
+ bid.tokenId,
82
+ "0",
83
+ bid.startBlock,
84
+ bid.expireBlock,
85
+ bid.bidToken
86
+ );
87
+
88
+ await verifyAccount(zAuction, data, bid.signedMessage, bid.bidder);
89
+
90
+ const tx = await zAuction.connect(signer).acceptBidV2(
91
+ bid.signedMessage,
92
+ bid.bidNonce,
93
+ bid.bidder,
94
+ bid.amount,
95
+ bid.tokenId,
96
+ "0", // minimum bid as string
97
+ bid.startBlock,
98
+ bid.expireBlock,
99
+ bid.bidToken
100
+ );
101
+
102
+ return tx;
103
+ }
104
+ // v2.0 bid
105
+ logger.trace(
106
+ `v2.0 Bid: Payment token for domain ${bid.tokenId} is ${config.wildTokenAddress}`
107
+ );
108
+ const data = await zAuction.createBid(
109
+ bid.bidNonce,
110
+ bid.amount,
111
+ bid.contract,
112
+ bid.tokenId,
113
+ "0",
114
+ bid.startBlock,
115
+ bid.expireBlock
116
+ );
117
+
118
+ await verifyAccount(zAuction, data, bid.signedMessage, bid.bidder);
119
+
120
+ const tx = await zAuction.connect(signer).acceptBid(
121
+ bid.signedMessage,
122
+ bid.bidNonce,
123
+ bid.bidder,
124
+ bid.amount,
125
+ bid.tokenId,
126
+ "0", // minimum bid
127
+ bid.startBlock,
128
+ bid.expireBlock
129
+ );
130
+ return tx;
131
+ }
132
+ //v1 legacy bid
133
+ const zAuctionV1: ZAuctionV1 = await getZAuctionV1Contract(
134
+ signer,
135
+ zAuctionAddress
136
+ );
137
+
138
+ logger.trace(
139
+ `v1.0 Bid: Payment token for domain ${bid.tokenId} is ${config.wildTokenAddress}`
140
+ );
141
+ const data = await zAuctionV1.createBid(
142
+ bid.bidNonce,
143
+ bid.amount,
144
+ bid.contract,
145
+ bid.tokenId,
146
+ "0",
147
+ bid.startBlock,
148
+ bid.expireBlock
149
+ );
150
+
151
+ await verifyAccount(zAuctionV1, data, bid.signedMessage, bid.bidder);
152
+
153
+ // For any v1 bid this will always return the default registrar
154
+ // const registrar = await hub.getRegistrarForDomain(bid.tokenId);
155
+ const tx = await zAuctionV1.connect(signer).acceptBid(
156
+ bid.signedMessage,
157
+ bid.bidNonce,
158
+ bid.bidder,
159
+ bid.amount,
160
+ bid.contract,
161
+ bid.tokenId,
162
+ "0", // minimum bid as string
163
+ bid.startBlock,
164
+ bid.expireBlock
165
+ );
166
+ return tx;
167
+ };
@@ -0,0 +1,25 @@
1
+ import { ethers } from "ethers";
2
+ import { getERC721Contract } from "../contracts";
3
+
4
+ import { getLogger } from "../utilities";
5
+
6
+ const logger = getLogger("actions:approveDomainTransfer");
7
+
8
+ // Approve zAuction to transfer domains on behalf of the signer
9
+ export const approveDomainTransfer = async (
10
+ domainContractAddress: string,
11
+ zAuctionAddress: string,
12
+ signer: ethers.Signer
13
+ ): Promise<ethers.ContractTransaction> => {
14
+ const signerAddress = await signer.getAddress();
15
+ const nftContract = await getERC721Contract(signer, domainContractAddress);
16
+
17
+ const tx = await nftContract
18
+ .connect(signer)
19
+ .setApprovalForAll(zAuctionAddress, true);
20
+
21
+ logger.trace(
22
+ `User ${signerAddress} has approved zAuction to transfer domains from ${domainContractAddress}`
23
+ );
24
+ return tx;
25
+ };
@@ -0,0 +1,27 @@
1
+ import { ethers } from "ethers";
2
+ import { getERC20Contract } from "../contracts";
3
+ import { IERC20 } from "../contracts/types";
4
+ import { getLogger } from "../utilities";
5
+
6
+ const logger = getLogger("actions:approveSpender");
7
+
8
+ // Approve zAuction to spend ERC20 tokens on behalf of the signer
9
+ export const approveSpender = async (
10
+ paymentTokenAddress: string,
11
+ zAuctionAddress: string,
12
+ signer: ethers.Signer
13
+ ): Promise<ethers.ContractTransaction> => {
14
+ const signerAddress = await signer.getAddress();
15
+
16
+ const paymentToken: IERC20 = await getERC20Contract(
17
+ signer,
18
+ paymentTokenAddress
19
+ );
20
+ const tx = await paymentToken
21
+ .connect(signer)
22
+ .approve(zAuctionAddress, ethers.constants.MaxUint256);
23
+ logger.trace(
24
+ `User ${signerAddress} has approved zAuction to spend ${paymentToken}`
25
+ );
26
+ return tx;
27
+ };
@@ -0,0 +1,109 @@
1
+ import { ethers } from "ethers";
2
+ import {
3
+ getERC721Contract,
4
+ getZAuctionContract,
5
+ getZnsHubContract,
6
+ } from "../contracts";
7
+ import { ZAuction } from "../contracts/types";
8
+ import { BuyNowParams, Config, BuyNowListing } from "../types";
9
+ import { getPaymentTokenAllowance } from "./getPaymentTokenAllowance";
10
+ import { isZAuctionApprovedNftTransfer } from "./isZAuctionApproved";
11
+ import { getLogger } from "../utilities";
12
+
13
+ const logger = getLogger("actions:buyNow");
14
+
15
+ // Perform an immediate buy, supporting legacy domain listings
16
+ export const buyNow = async (
17
+ params: BuyNowParams,
18
+ signer: ethers.Signer,
19
+ config: Config
20
+ ): Promise<ethers.ContractTransaction> => {
21
+ const buyer = await signer.getAddress();
22
+
23
+ logger.trace(
24
+ `Calling from user ${buyer} for domain ${params.tokenId} to buy now`
25
+ );
26
+ const hub = await getZnsHubContract(signer, config.znsHubAddress);
27
+ const tokenContract = await hub.getRegistrarForDomain(params.tokenId);
28
+
29
+ const nftContract = await getERC721Contract(signer, tokenContract);
30
+
31
+ const seller = await nftContract.ownerOf(params.tokenId);
32
+
33
+ const isApproved = await isZAuctionApprovedNftTransfer(
34
+ seller,
35
+ config.zAuctionAddress,
36
+ nftContract
37
+ );
38
+
39
+ if (!isApproved) {
40
+ throw Error("Seller did not approve zAuction to transfer NFT");
41
+ }
42
+
43
+ if (seller === buyer) {
44
+ throw Error("Cannot sell a domain to yourself");
45
+ }
46
+
47
+ const zAuction: ZAuction = await getZAuctionContract(
48
+ signer,
49
+ config.zAuctionAddress
50
+ );
51
+
52
+ const listing: BuyNowListing = await zAuction.priceInfo(params.tokenId);
53
+
54
+ if (listing.price.eq("0")) {
55
+ throw Error("Domain is not for sale");
56
+ }
57
+ if (!listing.price.eq(params.amount)) {
58
+ throw Error("Incorrect buyNow price given");
59
+ }
60
+
61
+ if (
62
+ !listing.paymentToken ||
63
+ listing.paymentToken === ethers.constants.AddressZero
64
+ ) {
65
+ logger.trace(
66
+ `Payment token for domain ${params.tokenId} is ${config.wildTokenAddress}`
67
+ );
68
+ // If no bidToken exists it is not a v2.1 listing, use WILD
69
+ const allowance = await getPaymentTokenAllowance(
70
+ buyer,
71
+ config.wildTokenAddress,
72
+ config.web3Provider,
73
+ config.zAuctionAddress
74
+ );
75
+
76
+ // Ensure buyer has approved zAuction to transfer tokens on their behalf
77
+ if (allowance.lt(params.amount)) {
78
+ throw Error("zAuction is not approved to transfer this many tokens");
79
+ }
80
+
81
+ const tx = await zAuction
82
+ .connect(signer)
83
+ .buyNow(params.amount, params.tokenId);
84
+
85
+ return tx;
86
+ }
87
+
88
+ logger.trace(
89
+ `Payment token for domain ${params.tokenId} is ${listing.paymentToken}`
90
+ );
91
+
92
+ const allowance = await getPaymentTokenAllowance(
93
+ buyer,
94
+ listing.paymentToken,
95
+ config.web3Provider,
96
+ config.zAuctionAddress
97
+ );
98
+
99
+ // Ensure buyer has approved zAuction to transfer tokens on their behalf
100
+ if (allowance.lt(params.amount)) {
101
+ throw Error("zAuction is not approved to transfer this many tokens");
102
+ }
103
+
104
+ const tx = await zAuction
105
+ .connect(signer)
106
+ .buyNowV2(params.amount, params.tokenId);
107
+
108
+ return tx;
109
+ };
@@ -0,0 +1,37 @@
1
+ import { ethers } from "ethers";
2
+ import { ApiClient } from "../api";
3
+ import { getZAuctionContract } from "../contracts";
4
+ import { Bid } from "../types";
5
+ import { getLogger } from "../utilities";
6
+
7
+ const logger = getLogger("actions:cancelBid");
8
+
9
+ // Cancel a bid for a domain, supporting legacy bids
10
+ export const cancelBid = async (
11
+ bid: Bid,
12
+ cancelOnChain: boolean,
13
+ apiClient: ApiClient,
14
+ zAuctionAddress: string,
15
+ signer: ethers.Signer
16
+ ): Promise<ethers.ContractTransaction | void> => {
17
+ logger.trace(
18
+ `Calling to cancel a bid by user ${bid.bidder} with bid nonce of ${bid.bidNonce}`
19
+ );
20
+ const encodedCancelMessage = await apiClient.encodeCancelBid(
21
+ bid.signedMessage
22
+ );
23
+ const signedCancelMessage = await signer.signMessage(encodedCancelMessage);
24
+
25
+ // Always cancel the bid through the API
26
+ await apiClient.submitCancelBid(signedCancelMessage, bid.signedMessage);
27
+
28
+ // If enabled, also cancel the bid with the zAuction smart contract
29
+ if (cancelOnChain) {
30
+ const zAuction = await getZAuctionContract(signer, zAuctionAddress);
31
+
32
+ const account = await signer.getAddress();
33
+
34
+ const tx = await zAuction.connect(signer).cancelBid(account, bid.bidNonce);
35
+ return tx;
36
+ }
37
+ };
@@ -0,0 +1,65 @@
1
+ import { ethers } from "ethers";
2
+ import {
3
+ getERC721Contract,
4
+ getZAuctionContract,
5
+ getZnsHubContract,
6
+ } from "../contracts";
7
+ import { BuyNowListing, Config } from "../types";
8
+ import { Maybe, getLogger } from "../utilities";
9
+
10
+ const logger = getLogger("actions:getBuyNowListing");
11
+
12
+ export const getBuyNowListing = async (
13
+ tokenId: string,
14
+ config: Config
15
+ ): Promise<Maybe<BuyNowListing>> => {
16
+ if (!tokenId || tokenId === ethers.constants.HashZero) {
17
+ throw Error("Must provide a valid tokenId");
18
+ }
19
+
20
+ const contract = await getZAuctionContract(
21
+ config.web3Provider,
22
+ config.zAuctionAddress
23
+ );
24
+
25
+ const hub = await getZnsHubContract(
26
+ config.web3Provider,
27
+ config.znsHubAddress
28
+ );
29
+
30
+ const registrarAddress = await hub.getRegistrarForDomain(tokenId);
31
+
32
+ const tokenContract = await getERC721Contract(
33
+ config.web3Provider,
34
+ registrarAddress
35
+ );
36
+
37
+ const owner = await tokenContract.ownerOf(tokenId);
38
+ const listing: BuyNowListing = await contract.priceInfo(tokenId);
39
+
40
+ if (listing.holder !== owner) {
41
+ logger.trace(
42
+ `Domain with ID ${tokenId} has changed owners since this buyNow listing was created so it is invalid`
43
+ );
44
+ return undefined;
45
+ }
46
+
47
+ if (listing.price.eq("0")) {
48
+ logger.trace(
49
+ `Domain with ID ${tokenId} is currently not listed for buyNow`
50
+ );
51
+ return undefined;
52
+ }
53
+
54
+ if (listing.paymentToken === ethers.constants.AddressZero) {
55
+ // Object is readonly, must make a new listing with payment token info
56
+ const newListing: BuyNowListing = {
57
+ holder: listing.holder,
58
+ price: listing.price,
59
+ paymentToken: config.wildTokenAddress,
60
+ };
61
+ return newListing;
62
+ }
63
+
64
+ return listing;
65
+ };
@@ -0,0 +1,30 @@
1
+ import { ethers } from "ethers";
2
+ import { getERC20Contract } from "../contracts";
3
+ import { IERC20 } from "../contracts/types";
4
+ import { getLogger } from "../utilities";
5
+
6
+ const logger = getLogger("actions:getPaymentTokenAllowance");
7
+
8
+ // Return the amount the given account has allowed zAuction to spend on its behalf
9
+ export const getPaymentTokenAllowance = async (
10
+ account: string,
11
+ paymentTokenAddress: string,
12
+ provider: ethers.providers.Provider | ethers.Signer,
13
+ zAuctionAddress: string
14
+ ): Promise<ethers.BigNumber> => {
15
+ logger.trace(
16
+ `Calling to get allowance for user ${account} with payment token ${paymentTokenAddress}`
17
+ );
18
+ const paymentToken: IERC20 = await getERC20Contract(
19
+ provider,
20
+ paymentTokenAddress
21
+ );
22
+ const allowance = await paymentToken.allowance(account, zAuctionAddress);
23
+
24
+ logger.trace(
25
+ `User ${account} has allowance of ${ethers.utils
26
+ .formatEther(allowance)
27
+ .toString()} for payment token ${paymentToken}`
28
+ );
29
+ return allowance;
30
+ };
@@ -0,0 +1,11 @@
1
+ export * from "./placeBid";
2
+ export * from "./isZAuctionApproved";
3
+ export * from "./acceptBid";
4
+ export * from "./cancelBid";
5
+ export * from "./buyNow";
6
+ export * from "./approveSpender";
7
+ export * from "./approveDomainTransfer";
8
+ export * from "./getPaymentTokenAllowance";
9
+ export * from "./getBuyNowListing";
10
+ export * from "./setNetworkPaymentToken";
11
+ export * from "./setBuyNowPrice";
@@ -0,0 +1,20 @@
1
+ import { IERC721 } from "../contracts/types";
2
+ import { getLogger } from "../utilities";
3
+
4
+ const logger = getLogger("actions:isZAuctionApprovedNftTransfer");
5
+
6
+ // Check whether or not zAuction is approved to transfer NFTs for the user
7
+ export const isZAuctionApprovedNftTransfer = async (
8
+ account: string,
9
+ zAuctionAddress: string,
10
+ nftContract: IERC721
11
+ ): Promise<boolean> => {
12
+ const isApproved = await nftContract.isApprovedForAll(
13
+ account,
14
+ zAuctionAddress
15
+ );
16
+ logger.trace(
17
+ `User ${account} has approved zAuction to transfer NFTs: ${isApproved}`
18
+ );
19
+ return isApproved;
20
+ };
@@ -0,0 +1,102 @@
1
+ import { ethers } from "ethers";
2
+ import { BidParameters, SignableBid, SignedBid } from "../api/types";
3
+ import { getZAuctionContract, getZnsHubContract } from "../contracts";
4
+
5
+ import {
6
+ PlaceBidStatus,
7
+ PlaceBidStatusCallback,
8
+ NewBidParameters,
9
+ Config,
10
+ } from "../types";
11
+ import { Maybe } from "../utilities";
12
+ import { getLogger } from "../utilities";
13
+
14
+ const logger = getLogger("actions:placeBid");
15
+
16
+ type SignMessageFunction = (
17
+ message: string | ethers.utils.Bytes
18
+ ) => Promise<string>;
19
+ type EncodeBidFunction = (bidParams: BidParameters) => Promise<SignableBid>;
20
+ type SubmitBidFunction = (signedBid: SignedBid) => Promise<void>;
21
+
22
+ export interface PlaceBidActionParameters {
23
+ bid: NewBidParameters;
24
+ config: Config;
25
+ bidder: string;
26
+ encodeBid: EncodeBidFunction;
27
+ signMessage: SignMessageFunction;
28
+ submitBid: SubmitBidFunction;
29
+ statusCallback?: PlaceBidStatusCallback;
30
+ }
31
+
32
+ export const placeBid = async (
33
+ params: PlaceBidActionParameters
34
+ ): Promise<void> => {
35
+ params.statusCallback ? params.statusCallback(PlaceBidStatus.Encoding) : null;
36
+
37
+ const contract = await getZAuctionContract(
38
+ params.config.web3Provider,
39
+ params.config.zAuctionAddress
40
+ );
41
+ const paymentToken = await contract.getPaymentTokenForDomain(
42
+ params.bid.tokenId
43
+ );
44
+ logger.trace(
45
+ `Calling to place a bid by user ${params.bidder} for ${params.bid.bidAmount} of ERC20 token ${paymentToken} on domain ${params.bid.tokenId}`
46
+ );
47
+
48
+ const hub = await getZnsHubContract(
49
+ params.config.web3Provider,
50
+ params.config.znsHubAddress
51
+ );
52
+ const registrar = await hub.getRegistrarForDomain(params.bid.tokenId);
53
+
54
+ let signableBid: Maybe<SignableBid>;
55
+
56
+ const bidParams: BidParameters = {
57
+ bidder: params.bidder,
58
+ tokenId: params.bid.tokenId,
59
+ contract: registrar,
60
+ amount: params.bid.bidAmount,
61
+ startBlock: params.bid.startBlock ?? "0",
62
+ expireBlock: params.bid.expireBlock ?? "9999999999",
63
+ bidToken: paymentToken,
64
+ };
65
+ try {
66
+ signableBid = await params.encodeBid(bidParams);
67
+ } catch (e) {
68
+ throw Error(`Failed to encode bid: ${e}`);
69
+ }
70
+
71
+ params.statusCallback ? params.statusCallback(PlaceBidStatus.Signing) : null;
72
+
73
+ let signedBidMessage: Maybe<string>;
74
+ try {
75
+ signedBidMessage = await params.signMessage(
76
+ ethers.utils.arrayify(signableBid.message)
77
+ );
78
+ } catch (e) {
79
+ throw Error(`Failed to sign bid message: ${e}`);
80
+ }
81
+
82
+ params.statusCallback
83
+ ? params.statusCallback(PlaceBidStatus.Submitting)
84
+ : null;
85
+
86
+ try {
87
+ await params.submitBid({
88
+ bid: signableBid.bid,
89
+ signedMessage: signedBidMessage,
90
+ } as SignedBid);
91
+ } catch (e) {
92
+ throw Error(`Failed to submit bid: ${e}`);
93
+ }
94
+
95
+ logger.trace(
96
+ `Bid with bidNonce of ${signableBid.bid.bidNonce} submitted successfully`
97
+ );
98
+
99
+ params.statusCallback
100
+ ? params.statusCallback(PlaceBidStatus.Completed)
101
+ : null;
102
+ };
@@ -0,0 +1,56 @@
1
+ import { ethers } from "ethers";
2
+ import {
3
+ getERC721Contract,
4
+ getZAuctionContract,
5
+ getZnsHubContract,
6
+ } from "../contracts";
7
+ import { IZNSHub } from "../contracts/types";
8
+ import { BuyNowParams } from "../types";
9
+
10
+ import { isZAuctionApprovedNftTransfer } from "./isZAuctionApproved";
11
+
12
+ export const setBuyNowPrice = async (
13
+ params: BuyNowParams,
14
+ signer: ethers.Signer,
15
+ znsHubAddress: string,
16
+ zAuctionAddress: string
17
+ ): Promise<ethers.ContractTransaction> => {
18
+ const hub: IZNSHub = await getZnsHubContract(signer, znsHubAddress);
19
+ const domainContract = await hub.getRegistrarForDomain(params.tokenId);
20
+
21
+ const nftContract = await getERC721Contract(signer, domainContract);
22
+
23
+ const owner = await nftContract.ownerOf(params.tokenId);
24
+ const givenSeller = await signer.getAddress();
25
+
26
+ if (givenSeller !== owner) {
27
+ throw Error("Cannot set the price of a domain that is not yours");
28
+ }
29
+
30
+ // Seller must have approved zAuction to transfer their NFT(s)
31
+ // before being able to set a buy price
32
+ const isApproved = await isZAuctionApprovedNftTransfer(
33
+ owner,
34
+ zAuctionAddress,
35
+ nftContract
36
+ );
37
+
38
+ if (!isApproved) {
39
+ throw Error("Seller did not approve zAuction to transfer NFT");
40
+ }
41
+
42
+ const contract = await getZAuctionContract(signer, zAuctionAddress);
43
+
44
+ const listing = await contract.priceInfo(params.tokenId);
45
+
46
+ if (listing.price.eq(params.amount)) {
47
+ throw Error(
48
+ "Unable to set price if a listing with that price already exists"
49
+ );
50
+ }
51
+
52
+ const tx = await contract
53
+ .connect(signer)
54
+ .setBuyPrice(params.amount, params.tokenId);
55
+ return tx;
56
+ };