@zero-tech/zauction-sdk 0.2.10 → 0.2.12
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +3 -2
- package/src/actions/acceptBid.ts +167 -0
- package/src/actions/approveDomainTransfer.ts +25 -0
- package/src/actions/approveSpender.ts +27 -0
- package/src/actions/buyNow.ts +109 -0
- package/src/actions/cancelBid.ts +37 -0
- package/src/actions/getBuyNowListing.ts +65 -0
- package/src/actions/getPaymentTokenAllowance.ts +30 -0
- package/src/actions/index.ts +11 -0
- package/src/actions/isZAuctionApproved.ts +20 -0
- package/src/actions/placeBid.ts +102 -0
- package/src/actions/setBuyNowPrice.ts +56 -0
- package/src/actions/setNetworkPaymentToken.ts +46 -0
- package/src/api/actions/encodeBid.ts +44 -0
- package/src/api/actions/encodeCancelMessage.ts +24 -0
- package/src/api/actions/helpers.ts +61 -0
- package/src/api/actions/index.ts +6 -0
- package/src/api/actions/listBidsForAccount.ts +24 -0
- package/src/api/actions/listBidsForTokens.ts +39 -0
- package/src/api/actions/submitBid.ts +28 -0
- package/src/api/actions/submitCancelMessage.ts +30 -0
- package/src/api/client.ts +78 -0
- package/src/api/index.ts +1 -0
- package/src/api/types.ts +47 -0
- package/src/contracts/index.ts +53 -0
- package/src/contracts/types/IERC20.d.ts +294 -0
- package/src/contracts/types/IERC721.d.ts +472 -0
- package/src/contracts/types/IZNSHub.d.ts +578 -0
- package/src/contracts/types/ZAuction.d.ts +1487 -0
- package/src/contracts/types/ZAuctionV1.d.ts +440 -0
- package/src/contracts/types/commons.ts +36 -0
- package/src/contracts/types/factories/IERC20__factory.ts +203 -0
- package/src/contracts/types/factories/IERC721__factory.ts +308 -0
- package/src/contracts/types/factories/IZNSHub__factory.ts +311 -0
- package/src/contracts/types/factories/ZAuctionV1__factory.ts +326 -0
- package/src/contracts/types/factories/ZAuction__factory.ts +1033 -0
- package/src/contracts/types/index.ts +14 -0
- package/src/index.ts +468 -0
- package/src/subgraph/actions/index.ts +4 -0
- package/src/subgraph/actions/listAllBuyNowListings.ts +69 -0
- package/src/subgraph/actions/listAllSales.ts +57 -0
- package/src/subgraph/actions/listBuyNowSales.ts +44 -0
- package/src/subgraph/actions/listSales.ts +33 -0
- package/src/subgraph/client.ts +62 -0
- package/src/subgraph/helpers/index.ts +39 -0
- package/src/subgraph/index.ts +1 -0
- package/src/subgraph/queries.ts +75 -0
- package/src/subgraph/types.ts +58 -0
- package/src/types.ts +181 -0
- package/src/utilities/index.ts +2 -0
- 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.
|
3
|
+
"version": "0.2.12",
|
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
|
+
};
|