Skip to content

Commit

Permalink
feat: WT-2044 orderExpiry in SmartCheckout (#1366)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrearampin authored Jan 18, 2024
1 parent bd4fa06 commit 623d86f
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 25 deletions.
36 changes: 31 additions & 5 deletions packages/checkout/sdk-sample-app/src/components/Listings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@ interface ListingsProps {
export default function Listings({ checkout, provider }: ListingsProps) {
const [sellContractAddress, setSellContractAddress] = useState<string>('');
const [orderIdError, setAddressError] = useState<any>(null);

const [listingId, setListingId] = useState<string>('');
const [listingIdError, setListingIdError] = useState<any>(null);

const [error, setError] = useState<any>(null);
const [loading, setLoading] = useState<boolean>(false);

async function getListingsClick() {
if (!sellContractAddress) {
if (!sellContractAddress && !listingId) {
setAddressError('Please enter an collection address');
setListingIdError('Or enter an collection address');
return;
}
if (!checkout) {
Expand All @@ -34,12 +39,18 @@ export default function Listings({ checkout, provider }: ListingsProps) {
setError(null);
setLoading(true);
try {
const orderBook = new Orderbook({baseConfig: {environment: checkout.config.environment}})
const listingsResult = await orderBook.listListings({
const orderBook = new Orderbook({baseConfig: {environment: checkout.config.environment}})

if (listingId) {
const result = await orderBook.getListing(listingId)
console.log('listings:', result)
} else {
const result = await orderBook.listListings({
sellItemContractAddress: sellContractAddress,
status: OrderStatusName.ACTIVE
})
console.log('listings:', listingsResult)
console.log('listings:', result)
}
setLoading(false);
} catch (err: any) {
setError(err);
Expand All @@ -54,6 +65,13 @@ export default function Listings({ checkout, provider }: ListingsProps) {
const updateSellContractAddress = (event: any) => {
setSellContractAddress(event.target.value);
setAddressError('');
setListingIdError('');
}

const updateListingId = (event: any) => {
setListingId(event.target.value);
setAddressError('');
setListingIdError('');
}

useEffect(() => {
Expand All @@ -64,13 +82,21 @@ export default function Listings({ checkout, provider }: ListingsProps) {
return (
<Box>
<FormControl validationStatus={orderIdError ? 'error' : 'success'} >
<FormControl.Label>Sell Collection Address</FormControl.Label>
<FormControl.Label>Collection Address</FormControl.Label>
<TextInput onChange={updateSellContractAddress} />
{orderIdError && (
<FormControl.Validation>{orderIdError}</FormControl.Validation>
)}
</FormControl>
<br />
<FormControl validationStatus={orderIdError ? 'error' : 'success'} >
<FormControl.Label>Listing Id (optional)</FormControl.Label>
<TextInput onChange={updateListingId} />
{listingIdError && (
<FormControl.Validation>{listingIdError}</FormControl.Validation>
)}
</FormControl>
<br />
<LoadingButton onClick={getListingsClick} loading={loading}>
Get Listings
</LoadingButton>
Expand Down
32 changes: 31 additions & 1 deletion packages/checkout/sdk-sample-app/src/components/Sell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,19 @@ export default function Sell({ checkout, provider }: SellProps) {
const [listingTypeError, setListingTypeError] = useState<string>('');
const [amount, setAmount] = useState<string>('');
const [amountError, setAmountError] = useState<string>('');
const [expiry, setExpiry] = useState<string | undefined>(undefined);
const [expiryError, setExpiryError] = useState<string>('');
const [tokenAddress, setTokenAddress] = useState<string>('');
const [contractAddressError, setContractAddressError] = useState<string>('');
const [error, setError] = useState<any>(null);
const [success, setSuccess] = useState<boolean>(false);
const [loading, setLoading] = useState<boolean>(false);

const isDateValid = (dateStr: string) => {
var dateRegex = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})Z)?$/;
return dateRegex.test(dateStr);
}

const getBuyToken = (): BuyToken => {
if (listingType === ItemType.NATIVE) {
return {
Expand All @@ -45,21 +52,31 @@ export default function Sell({ checkout, provider }: SellProps) {
async function sellClick() {
if (!id) {
setIdError('Please enter the ID of the ERC721');
return
}
if (!collectionAddress) {
setCollectionAddressError('Please enter the collection address for the ERC721');
return
}
if (!listingType) {
setListingTypeError('Please select the listing type');
return
}
if (listingType === ItemType.NATIVE && !amount) {
setAmountError('Please enter the amount of NATIVE tokens to sell the ERC721 for');
return
}
if (listingType === ItemType.ERC20 && !amount) {
setAmountError('Please enter the amount of ERC20 tokens to sell the ERC721 for');
return
}
if (listingType === ItemType.ERC20 && !tokenAddress) {
setContractAddressError('Please enter the contract address for the ERC20');
return
}
if (expiry && !isDateValid(expiry)) {
setExpiryError('Invalid date - format YYYY-MM-DD or YYYY-MM-DDTHH:MM:SSZ');
return
}
if (!id ||
!collectionAddress ||
Expand Down Expand Up @@ -89,7 +106,8 @@ export default function Sell({ checkout, provider }: SellProps) {
makerFees: [{
amount: { percentageDecimal: 0.025 },
recipient: '0xEac347177DbA4a190B632C7d9b8da2AbfF57c772'
}]
}],
orderExpiry: expiry ? new Date(expiry) : undefined
}]

const result = await checkout.sell({
Expand Down Expand Up @@ -118,6 +136,11 @@ export default function Sell({ checkout, provider }: SellProps) {
setCollectionAddressError('');
}

const updateExpiry = (event: any) => {
setExpiry(event.target.value);
setError('');
}

const updateAmount = (event: any) => {
const value = event.target.value;
setAmount(value);
Expand Down Expand Up @@ -226,6 +249,13 @@ export default function Sell({ checkout, provider }: SellProps) {
<FormControl.Validation>{collectionAddressError}</FormControl.Validation>
)}
</FormControl>
<FormControl validationStatus={expiryError ? 'error' : 'success'} >
<FormControl.Label>Expiry</FormControl.Label>
<TextInput onChange={updateExpiry} />
{expiryError && (
<FormControl.Validation>{expiryError}</FormControl.Validation>
)}
</FormControl>
{tokenForm()}
<br />
<Box sx={{display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 'base.spacing.x2'}}>
Expand Down
55 changes: 38 additions & 17 deletions packages/checkout/sdk/src/smartCheckout/sell/sell.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@ jest.mock('../actions');

describe('sell', () => {
const seaportContractAddress = '0xSEAPORT';
const walletAddress = '0xADDRESS';
let config: CheckoutConfiguration;
let mockProvider: Web3Provider;

beforeEach(() => {
mockProvider = {
getSigner: jest.fn().mockReturnValue({
getAddress: jest.fn().mockResolvedValue('0xADDRESS'),
getAddress: jest.fn().mockResolvedValue(walletAddress),
}),
} as unknown as Web3Provider;

Expand Down Expand Up @@ -89,30 +90,35 @@ describe('sell', () => {
erc721TransactionRequirement,
],
});

const mockCreateListing = jest.fn().mockResolvedValue({
result: {
id: '1234',
},
});

const prepareListing = jest.fn().mockResolvedValue({
actions: [
{
type: ActionType.SIGNABLE,
purpose: SignablePurpose.CREATE_LISTING,
message: {
domain: '',
types: '',
value: '',
},
},
],
});

(createOrderbookInstance as jest.Mock).mockReturnValue({
config: jest.fn().mockReturnValue({
seaportContractAddress,
}),
prepareListing: jest.fn().mockResolvedValue({
actions: [
{
type: ActionType.SIGNABLE,
purpose: SignablePurpose.CREATE_LISTING,
message: {
domain: '',
types: '',
value: '',
},
},
],
}),
prepareListing,
createListing: mockCreateListing,
});

(getUnsignedMessage as jest.Mock).mockReturnValue(
{
orderHash: 'hash',
Expand All @@ -136,7 +142,8 @@ describe('sell', () => {
type: SignTransactionStatusType.SUCCESS,
});

const orders:Array<SellOrder> = [{
const orderExpiry = new Date('2022-03-25');
const order: SellOrder = {
sellToken: {
id,
collectionAddress: contractAddress,
Expand All @@ -149,12 +156,13 @@ describe('sell', () => {
amount: { percentageDecimal: 0.025 },
recipient: '0xEac347177DbA4a190B632C7d9b8da2AbfF57c772',
}],
}];
orderExpiry,
};

const result = await sell(
config,
mockProvider,
orders,
[order],
);

expect(result).toEqual({
Expand All @@ -178,6 +186,19 @@ describe('sell', () => {
},
},
);
expect(prepareListing).toBeCalledWith({
makerAddress: walletAddress,
buy: {
type: ItemType.NATIVE,
amount: '1000000000000000000',
},
sell: {
type: ItemType.ERC721,
contractAddress: order.sellToken.collectionAddress,
tokenId: order.sellToken.id,
},
orderExpiry: order.orderExpiry,
});
expect(signMessage).toBeCalledWith(
mockProvider,
{
Expand Down
8 changes: 7 additions & 1 deletion packages/checkout/sdk/src/smartCheckout/sell/sell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,12 @@ export const sell = async (
);
}

const { buyToken, sellToken, makerFees } = orders[0];
const {
buyToken,
sellToken,
makerFees,
orderExpiry,
} = orders[0];

let decimals = 18;
if (buyToken.type === ItemType.ERC20) {
Expand Down Expand Up @@ -121,6 +126,7 @@ export const sell = async (
contractAddress: sellToken.collectionAddress,
tokenId: sellToken.id,
},
orderExpiry,
}),
);
} catch (err: any) {
Expand Down
4 changes: 3 additions & 1 deletion packages/checkout/sdk/src/types/smartCheckout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,10 @@ export type SellOrder = {
sellToken: SellToken,
/** the token info of the price of the item */
buyToken: BuyToken,
/** option array of makerFees to be applied to the listing */
/** optional array of makerFees to be applied to the listing */
makerFees?: OrderFee[],
/** optional order expiry date. Default order expiry to 2 years from now */
orderExpiry?: Date;
};

/**
Expand Down

0 comments on commit 623d86f

Please sign in to comment.