Now, from the previous tutorial we have created a simple app data document. We will now use this document to create an order.
In doing so, we will be making use of:
Instantiate the SDK
We will start from the basic setup from the submit order tutorial and the simple app data tutorial. This has been populated in the code editor for you.
Quoting with app data
The keen eye-ed among you will notice that appDataHex
and appDataContent
are not used. Let's fix that. When we request a quote, we will pass appDataHex
and appDataContent
to the API. This allows the API to:
- validate the app data document and its hash (
appDataHex
) - wrap the app data into the response object
- determine any additional fees that may be required (if the app data document contains hooks)
// ...
export async function run(provider: Web3Provider): Promise<unknown> {
// ...
const quoteRequest: OrderQuoteRequest = {
sellToken,
buyToken,
from: ownerAddress,
receiver: ownerAddress,
sellAmountBeforeFee: sellAmount,
kind: OrderQuoteSideKindSell.SELL,
appData: appDataContent,
appDataHash: appDataHex,
};
// ...
}
Signing with app data
When signing an order, we need to make sure that we have set the appData
correctly. In this case, the UnsignedOrder
used by the OrderSigningUtils
class has an appData
field which should be set to the appDataHex
value.
// ...
export async function run(provider: Web3Provider): Promise<unknown> {
// ...
const order: UnsignedOrder = {
...quote,
receiver: ownerAddress,
appData: appDataHex,
}
// ...
}
Run the code
To run the code, we can press the "Run" button in the bottom right panel (the web container).
When running the script, we may be asked to connect a wallet. We can use Rabby for this.
- Accept the connection request in Rabby
- Press the "Run" button again
- Observe the
orderId
returned to the output panel
You can now use the orderId
to check the status of the order on CoW Explorer. Within the order details page, you can also see the app data document that was used to create the order.
Errors
The usual API errors from the submit order tutorial may occur. In addition, the following errors may occur:
InvalidAppData
: The app data passed to the API is not eitherbytes32
or a stringified JSON object.AppDataHashMismatch
: The hash of the app data document doesn't match theappDataHash
field provided in the order. This may be due to the app data document being modified after the order was signed.
import type { Web3Provider } from '@ethersproject/providers'
import {
OrderBookApi,
SupportedChainId,
OrderQuoteRequest,
OrderQuoteSideKindSell,
OrderSigningUtils,
UnsignedOrder,
SigningScheme
} from '@cowprotocol/cow-sdk'
import { MetadataApi, latest } from '@cowprotocol/app-data'
export async function run(provider: Web3Provider): Promise<unknown> {
const chainId = +(await provider.send('eth_chainId', []));
if (chainId !== SupportedChainId.GNOSIS_CHAIN) {
throw new Error(`Please connect to the Gnosis chain. ChainId: ${chainId}`);
}
const orderBookApi = new OrderBookApi({ chainId: SupportedChainId.GNOSIS_CHAIN });
const metadataApi = new MetadataApi()
const appCode = 'Decentralized CoW'
const environment = 'production'
const referrer = { address: `0xcA771eda0c70aA7d053aB1B25004559B918FE662` }
const quoteAppDoc: latest.Quote = { slippageBips: '50' }
const orderClass: latest.OrderClass = { orderClass: 'market' }
const appDataDoc = await metadataApi.generateAppDataDoc({
appCode,
environment,
metadata: {
referrer,
quote: quoteAppDoc,
orderClass
},
})
const { appDataHex, appDataContent } = await metadataApi.appDataToCid(appDataDoc)
const signer = provider.getSigner();
const ownerAddress = await signer.getAddress();
const sellToken = '0xe91d153e0b41518a2ce8dd3d7944fa863463a97d'; // wxDAI
const buyToken = '0x177127622c4A00F3d409B75571e12cB3c8973d3c'; // COW
const sellAmount = '1000000000000000000'; // 1 wxDAI
const quoteRequest: OrderQuoteRequest = {
sellToken,
buyToken,
from: ownerAddress,
receiver: ownerAddress,
sellAmountBeforeFee: sellAmount,
kind: OrderQuoteSideKindSell.SELL,
};
const { quote } = await orderBookApi.getQuote(quoteRequest);
const order: UnsignedOrder = {
...quote,
receiver: ownerAddress,
}
const orderSigningResult = await OrderSigningUtils.signOrder(
order,
chainId,
signer
)
try {
const orderId = await orderBookApi.sendOrder({
...quote,
...orderSigningResult,
signingScheme: orderSigningResult.signingScheme as unknown as SigningScheme
})
return {
orderId,
}
} catch (e) {
return e
}
}