Skip to content

Commit

Permalink
[NO-CHANGELOG][TD-873] extend orderbook actions to include signable m…
Browse files Browse the repository at this point in the history
…essages (#680)
  • Loading branch information
Sam-Jeston committed Aug 14, 2023
1 parent 6aaa121 commit 3644310
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 139 deletions.
41 changes: 30 additions & 11 deletions packages/orderbook/src/seaport/seaport.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ import {
TransactionMethods,
} from '@opensea/seaport-js/lib/types';
import {
ERC20Item, ERC721Item, NativeItem, RoyaltyInfo, TransactionType,
ActionType,
TransactionAction,
ERC20Item,
ERC721Item,
NativeItem,
RoyaltyInfo,
SignableAction,
TransactionPurpose,
} from 'types';
import { BigNumber, PopulatedTransaction, providers } from 'ethers';
import { CreateOrderProtocolData, Order, OrderStatus } from 'openapi/sdk';
Expand Down Expand Up @@ -141,11 +148,14 @@ describe('Seaport', () => {
orderStart,
orderExpiry,
);
expect(actions.length).toBe(0);
const approvalAction = actions.find(
(a): a is TransactionAction => a.type === ActionType.TRANSACTION,
);
expect(approvalAction).toBeUndefined();
});

it('returns the expected typedOrderMessageForSigning', async () => {
const { typedOrderMessageForSigning } = await sut.prepareSeaportOrder(
const { actions } = await sut.prepareSeaportOrder(
offerer,
listingItem,
considerationItem,
Expand All @@ -160,7 +170,10 @@ describe('Seaport', () => {
verifyingContract: seaportContractAddress,
};

expect(typedOrderMessageForSigning).toEqual({
const signableAction = actions.find(
(a): a is SignableAction => a.type === ActionType.SIGNABLE,
)!;
expect(signableAction.message).toEqual({
domain: domainData,
types: EIP_712_ORDER_TYPE,
value: orderComponentsWithHexSalt,
Expand Down Expand Up @@ -319,9 +332,11 @@ describe('Seaport', () => {
orderStart,
orderExpiry,
);
expect(actions.length).toBe(1);
expect(actions[0].transactionType).toEqual(TransactionType.APPROVAL);
const unsignedApprovalTransaction = await actions[0].buildTransaction();
const approvalAction = actions.find(
(a): a is TransactionAction => a.type === ActionType.TRANSACTION,
)!;
expect(approvalAction.purpose).toEqual(TransactionPurpose.APPROVAL);
const unsignedApprovalTransaction = await approvalAction.buildTransaction();
expect(unsignedApprovalTransaction!.from).toEqual(
approvalTransaction.from,
);
Expand All @@ -332,7 +347,7 @@ describe('Seaport', () => {
});

it('returns the expected typedOrderMessageForSigning', async () => {
const { typedOrderMessageForSigning } = await sut.prepareSeaportOrder(
const { actions } = await sut.prepareSeaportOrder(
offerer,
listingItem,
considerationItem,
Expand All @@ -347,7 +362,11 @@ describe('Seaport', () => {
verifyingContract: seaportContractAddress,
};

expect(typedOrderMessageForSigning).toEqual({
const signableAction = actions.find(
(a): a is SignableAction => a.type === ActionType.SIGNABLE,
)!;

expect(signableAction.message).toEqual({
domain: domainData,
types: EIP_712_ORDER_TYPE,
value: orderComponentsWithHexSalt,
Expand Down Expand Up @@ -506,7 +525,7 @@ describe('Seaport', () => {
fulfiller,
);
const approvalAction = actions.find(
(action) => action.transactionType === TransactionType.APPROVAL,
(a): a is TransactionAction => a.purpose === TransactionPurpose.APPROVAL,
);
expect(approvalAction).toBeTruthy();
const unsignedApprovalTransaction = await approvalAction!.buildTransaction();
Expand All @@ -525,7 +544,7 @@ describe('Seaport', () => {
fulfiller,
);
const fulfillmentAction = actions.find(
(action) => action.transactionType === TransactionType.FULFILL_ORDER,
(a): a is TransactionAction => a.purpose === TransactionPurpose.FULFILL_ORDER,
);
const unsignedFulfillmentTransaction = await fulfillmentAction!.buildTransaction();
expect(unsignedFulfillmentTransaction).toBeTruthy();
Expand Down
38 changes: 25 additions & 13 deletions packages/orderbook/src/seaport/seaport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@ import {
PopulatedTransaction, providers,
} from 'ethers';
import {
Action,
ActionType,
ERC20Item,
ERC721Item,
FulfillOrderResponse,
NativeItem,
PrepareListingResponse,
RoyaltyInfo,
SignableAction,
SignablePurpose,
TransactionAction,
TransactionType,
TransactionPurpose,
} from 'types';
import { Order } from 'openapi/sdk';
import {
Expand Down Expand Up @@ -44,7 +48,7 @@ export class Seaport {
orderStart: Date,
orderExpiry: Date,
): Promise<PrepareListingResponse> {
const { actions } = await this.createSeaportOrder(
const { actions: seaportActions } = await this.createSeaportOrder(
offerer,
listingItem,
considerationItem,
Expand All @@ -53,19 +57,20 @@ export class Seaport {
orderExpiry,
);

const listingActions: TransactionAction[] = [];
const listingActions: Action[] = [];

const approvalAction = actions
const approvalAction = seaportActions
.find((action) => action.type === 'approval') as ApprovalAction | undefined;

if (approvalAction) {
listingActions.push({
type: ActionType.TRANSACTION,
purpose: TransactionPurpose.APPROVAL,
buildTransaction: prepareTransaction(approvalAction.transactionMethods),
transactionType: TransactionType.APPROVAL,
});
}

const createAction: CreateOrderAction | undefined = actions
const createAction: CreateOrderAction | undefined = seaportActions
.find((action) => action.type === 'create') as CreateOrderAction | undefined;

if (!createAction) {
Expand All @@ -75,9 +80,14 @@ export class Seaport {
const orderMessageToSign = await createAction.getMessageToSign();
const orderComponents = getOrderComponentsFromMessage(orderMessageToSign);

listingActions.push({
type: ActionType.SIGNABLE,
purpose: SignablePurpose.CREATE_LISTING,
message: await this.getTypedDataFromOrderComponents(orderComponents),
});

return {
actions: listingActions,
typedOrderMessageForSigning: await this.getTypedDataFromOrderComponents(orderComponents),
orderComponents,
orderHash: this.getSeaportLib().getOrderHash(orderComponents),
};
Expand All @@ -87,7 +97,7 @@ export class Seaport {
const orderComponents = await this.mapImmutableOrderToSeaportOrderComponents(order);
const seaportLib = this.getSeaportLib(order);

const { actions } = await seaportLib.fulfillOrders({
const { actions: seaportActions } = await seaportLib.fulfillOrders({
accountAddress: account,
fulfillOrderDetails: [{
order: {
Expand All @@ -100,26 +110,28 @@ export class Seaport {

const fulfillmentActions: TransactionAction[] = [];

const approvalAction = actions
const approvalAction = seaportActions
.find((action) => action.type === 'approval') as ApprovalAction | undefined;

if (approvalAction) {
fulfillmentActions.push({
type: ActionType.TRANSACTION,
buildTransaction: prepareTransaction(approvalAction.transactionMethods),
transactionType: TransactionType.APPROVAL,
purpose: TransactionPurpose.APPROVAL,
});
}

const fulfilOrderAction: ExchangeAction | undefined = actions
const fulfilOrderAction: ExchangeAction | undefined = seaportActions
.find((action) => action.type === 'exchange') as ExchangeAction | undefined;

if (!fulfilOrderAction) {
throw new Error('No exchange action found');
}

fulfillmentActions.push({
type: ActionType.TRANSACTION,
buildTransaction: prepareTransaction(fulfilOrderAction.transactionMethods),
transactionType: TransactionType.FULFILL_ORDER,
purpose: TransactionPurpose.FULFILL_ORDER,
});

return { actions: fulfillmentActions };
Expand Down Expand Up @@ -182,7 +194,7 @@ export class Seaport {

private async getTypedDataFromOrderComponents(
orderComponents: OrderComponents,
): Promise<PrepareListingResponse['typedOrderMessageForSigning']> {
): Promise<SignableAction['message']> {
const { chainId } = await this.provider.getNetwork();

const domainData = {
Expand Down
15 changes: 4 additions & 11 deletions packages/orderbook/src/test/cancel.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { Orderbook } from 'orderbook';
import { getLocalhostProvider } from './helpers/provider';
import { getOffererWallet } from './helpers/signers';
import { deployTestToken } from './helpers/erc721';
import { signAndSubmitTx, signMessage } from './helpers/sign-and-submit';
import { signAndSubmitTx } from './helpers/sign-and-submit';
import { waitForOrderToBeOfStatus } from './helpers/order';
import { getConfigFromEnv } from './helpers';
import { actionAll } from './helpers/actions';

describe('cancel order', () => {
it('should cancel the order', async () => {
Expand Down Expand Up @@ -39,22 +40,14 @@ describe('cancel order', () => {
},
});

await signAndSubmitTx(
(await listing.actions[0].buildTransaction()),
offerer,
provider,
);
const signature = await signMessage(
listing.typedOrderMessageForSigning,
offerer,
);
const signatures = await actionAll(listing.actions, offerer, provider);

const {
result: { id: orderId },
} = await sdk.createListing({
orderComponents: listing.orderComponents,
orderHash: listing.orderHash,
orderSignature: signature,
orderSignature: signatures[0],
});

await waitForOrderToBeOfStatus(sdk, orderId, OrderStatus.ACTIVE);
Expand Down
16 changes: 5 additions & 11 deletions packages/orderbook/src/test/create.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
/* eslint-disable no-await-in-loop */
/* eslint-disable no-restricted-syntax */
import { Environment } from '@imtbl/config';
import { OrderStatus } from 'openapi/sdk';
import { Orderbook } from 'orderbook';
import { getLocalhostProvider } from './helpers/provider';
import { getOffererWallet } from './helpers/signers';
import { deployTestToken } from './helpers/erc721';
import { signAndSubmitTx, signMessage } from './helpers/sign-and-submit';
import { waitForOrderToBeOfStatus } from './helpers/order';
import { getConfigFromEnv } from './helpers';
import { actionAll } from './helpers/actions';

describe('prepareListing and createOrder e2e', () => {
it('should create the order', async () => {
Expand Down Expand Up @@ -39,22 +41,14 @@ describe('prepareListing and createOrder e2e', () => {
},
});

await signAndSubmitTx(
(await listing.actions[0].buildTransaction()),
offerer,
provider,
);
const signature = await signMessage(
listing.typedOrderMessageForSigning,
offerer,
);
const signatures = await actionAll(listing.actions, offerer, provider);

const {
result: { id: orderId },
} = await sdk.createListing({
orderComponents: listing.orderComponents,
orderHash: listing.orderHash,
orderSignature: signature,
orderSignature: signatures[0],
});

await waitForOrderToBeOfStatus(sdk, orderId, OrderStatus.ACTIVE);
Expand Down
18 changes: 4 additions & 14 deletions packages/orderbook/src/test/expiry.demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ import {
getFulfillerWallet,
getLocalhostProvider,
getOffererWallet,
signAndSubmitTx,
signMessage,
TestToken,
waitForOrderToBeOfStatus,
} from './helpers';
import { actionAll } from './helpers/actions';

async function deployAndMintNftContract(wallet: Wallet): Promise<TestToken> {
const { contract } = await deployTestToken(wallet);
Expand Down Expand Up @@ -70,20 +69,11 @@ describe('', () => {
});

log('Signing and submitting approval transaction...');
// Sign and submit the approval transaction for the offerer
await signAndSubmitTx(
(await soonToExpireListing.actions[0].buildTransaction()),
offerer,
provider,
);

// Sign and submit the approval transaction for the offerer &
// Sign the EIP712 order message for the offerer. This is the signature that the order book API
// stores and allows the fulfiller to fulfil the order, as long as they also have a valid
// operator signature
const signature = await signMessage(
soonToExpireListing.typedOrderMessageForSigning,
offerer,
);
const signatures = await actionAll(soonToExpireListing.actions, offerer, provider);

log('Submitting order to orderbook API...');
// Submit the order creation request to the order book API
Expand All @@ -92,7 +82,7 @@ describe('', () => {
} = await sdk.createListing({
orderComponents: soonToExpireListing.orderComponents,
orderHash: soonToExpireListing.orderHash,
orderSignature: signature,
orderSignature: signatures[0],
});
log('Submitted order to orderbook API with expiry time set in the future');

Expand Down
Loading

0 comments on commit 3644310

Please sign in to comment.