@zero-tech/zauction-sdk 0.2.10 → 0.2.12
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.
- 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
|
+
};
|