Something
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import type { Web3Provider } from '@ethersproject/providers'
import { Contract } from '@ethersproject/contracts'
import { OrderBookApi, UnsignedOrder, OrderKind, SigningScheme, OrderCreation } from '@cowprotocol/cow-sdk'
import { MetadataApi, latest } from '@cowprotocol/app-data'
import { getSafeSdkAndKit } from './getSafeSdkAndKit'
import { SETTLEMENT_CONTRACT_ABI, SETTLEMENT_CONTRACT_ADDRESS } from './const'
export async function run(provider: Web3Provider): Promise<unknown> {
const safeAddress = '<PUT_YOUR_SAFE_ADDRESS>'
const appCode = '<YOUR_APP_CODE>'
const environment = 'prod'
// Slippage percent, it's 0 to 100
const quote = { slippageBips: '50' }
// "market" | "limit" | "liquidity"
const orderClass: latest.OrderClass = { orderClass: 'limit' }
// Get chainId and account from the current provider
const accounts = await provider.listAccounts()
const account = accounts[0]
const chainId = +(await provider.send('eth_chainId', []))
// CoW Protocol OrderBookApi instance
// It will be used to send the order to the order-book
const orderBookApi = new OrderBookApi({ chainId })
// Order creation requires meta information about the order
const metadataApi = new MetadataApi()
// Create the CoW Protocol Settlement contract instance
const settlementContract = new Contract(SETTLEMENT_CONTRACT_ADDRESS, SETTLEMENT_CONTRACT_ABI)
// Create the Safe SDK and Safe API Kit instances
const { safeApiKit, safeSdk } = await getSafeSdkAndKit(chainId, provider, safeAddress)
// The order
// Pay attention to the `signingScheme` field that is set to `SigningScheme.PRESIGN`
const defaultOrder: UnsignedOrder = {
receiver: safeAddress,
buyAmount: '650942340000000000000',
buyToken: '0x91056D4A53E1faa1A84306D4deAEc71085394bC8',
sellAmount: '100000000000000000',
sellToken: '0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6',
validTo: Math.round((Date.now() + 900_000) / 1000),
appData: '0x',
feeAmount: '0',
kind: OrderKind.SELL,
partiallyFillable: true,
signingScheme: SigningScheme.PRESIGN,
}
// Generate the app-data document
const appDataDoc = await metadataApi.generateAppDataDoc({
appCode,
environment,
metadata: {
quote,
orderClass
},
})
const { appDataHex, appDataContent } = await metadataApi.appDataToCid(appDataDoc)
// Add all necessary fields to the order creation request
const orderCreation: OrderCreation = {
...defaultOrder,
from: safeAddress,
signature: safeAddress,
appData: appDataContent,
appDataHash: appDataHex,
}
// Send order to CoW Protocol order-book
const orderId = await orderBookApi.sendOrder(orderCreation)
// Create the pre-signature transaction
const presignCallData = settlementContract.interface.encodeFunctionData('setPreSignature', [
orderId,
true,
])
const presignRawTx = {
to: settlementContract.address,
data: presignCallData,
value: '0',
}
// Send pre-signature transaction to settlement contract
// In this example we are using the Safe SDK, but you can use any other smart-contract wallet
const safeTx = await safeSdk.createTransaction({safeTransactionData: presignRawTx})
const signedSafeTx = await safeSdk.signTransaction(safeTx)
const safeTxHash = await safeSdk.getTransactionHash(signedSafeTx)
const senderSignature = signedSafeTx.signatures.get(account.toLowerCase())?.data || ''
// Send the pre-signed transaction to the Safe
await safeApiKit.proposeTransaction({
safeAddress,
safeTransactionData: signedSafeTx.data,
safeTxHash,
senderAddress: account,
senderSignature,
})
return { orderId, safeTxHash, senderSignature }
}