Skip to content

Commit 5ee02b4

Browse files
feat: create umbrella-sdk/02-individual-packages tutorial
1 parent d026894 commit 5ee02b4

File tree

8 files changed

+456
-9
lines changed

8 files changed

+456
-9
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
---
2+
title: Basic Usage
3+
---
4+
5+
This tutorial introduces how to use **individual packages** from the CoW Protocol SDK. While the CowSdk provides a unified interface, you can also import and use each package directly from `@cowprotocol/cow-sdk`.
6+
7+
## Core Packages Overview
8+
9+
The CoW Protocol SDK provides several individual packages:
10+
11+
### **📊 OrderBookApi**
12+
Handles order management and quotes:
13+
- **Standalone** - no adapter required
14+
- **Simple initialization** - just needs chainId
15+
- **Independent configuration** - custom rate limits, URLs, etc.
16+
17+
### **📋 MetadataApi**
18+
Generates and processes app data:
19+
- **Requires adapter** for blockchain operations
20+
- **Flexible adapter** - can use different adapters
21+
- **Blockchain aware** - can interact with on-chain data
22+
23+
### **✍️ OrderSigningUtils**
24+
Static utility class for signing orders:
25+
- **No initialization** needed
26+
- **Static methods** - call directly
27+
- **Uses signer** - pass signer to methods
28+
29+
## Basic Setup
30+
31+
Let's try using the packages individually:
32+
33+
```typescript
34+
/// file: run.ts
35+
import type { Web3Provider } from '@ethersproject/providers';
36+
import {
37+
OrderBookApi,
38+
MetadataApi,
39+
SupportedChainId
40+
} from '@cowprotocol/cow-sdk';
41+
import { EthersV5Adapter } from '@cowprotocol/sdk-ethers-v5-adapter';
42+
43+
export async function run(provider: Web3Provider): Promise<unknown> {
44+
const signer = provider.getSigner();
45+
const adapter = new EthersV5Adapter({ provider, signer });
46+
47+
// Initialize packages individually
48+
const orderBookApi = new OrderBookApi({ chainId });
49+
const metadataApi = new MetadataApi(adapter);
50+
51+
// Test OrderBookApi
52+
const order = await orderBookApi.getOrder(orderUid);
53+
54+
// Test MetadataApi
55+
const appDataDoc = await metadataApi.generateAppDataDoc({
56+
appCode: 'Individual Basic Usage',
57+
environment: 'production',
58+
metadata: {
59+
quote: { slippageBips: 50 },
60+
orderClass: { orderClass: 'market' }
61+
}
62+
});
63+
64+
return { order, appDataDoc };
65+
}
66+
```
67+
68+
## Package-Specific Configuration
69+
70+
Each package can be configured independently:
71+
72+
```typescript
73+
/// file: run.ts
74+
// OrderBookApi with custom config
75+
const orderBookApi = new OrderBookApi({
76+
chainId,
77+
env: 'prod',
78+
backoffOpts: { maxDelay: 3000, numOfAttempts: 3 },
79+
baseUrls: {
80+
[SupportedChainId.GNOSIS_CHAIN]: 'https://api.cow.fi/xdai'
81+
}
82+
});
83+
84+
// MetadataApi with different adapters
85+
const readOnlyAdapter = new EthersV5Adapter({ provider });
86+
const signingAdapter = new EthersV5Adapter({ provider, signer });
87+
88+
const readOnlyMetadata = new MetadataApi(readOnlyAdapter);
89+
const signingMetadata = new MetadataApi(signingAdapter);
90+
```
91+
92+
## Run the Code
93+
94+
1. Accept the wallet connection request
95+
2. Press the "Run" button
96+
3. Observe the packages working independently
97+
98+
Example output:
99+
```json
100+
{
101+
"orderBook": {
102+
"uid": "0x8464af...",
103+
"status": "fulfilled"
104+
},
105+
"metadata": {
106+
"appDataHex": "0xe269b..."
107+
}
108+
}
109+
```
110+
111+
## What's Next?
112+
113+
Now that you understand the basics of individual packages, the next tutorial will show you how to build a complete trading workflow using these packages together.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type { Web3Provider } from '@ethersproject/providers';
2+
import { OrderBookApi, SupportedChainId } from '@cowprotocol/cow-sdk';
3+
4+
export async function run(provider: Web3Provider): Promise<unknown> {
5+
const chainId = +(await provider.send('eth_chainId', []));
6+
if (chainId !== SupportedChainId.GNOSIS_CHAIN) {
7+
throw new Error(`Please connect to the Gnosis chain. ChainId: ${chainId}`);
8+
}
9+
10+
// TODO: Initialize OrderBookApi individually
11+
// TODO: Test basic functionality
12+
13+
return {};
14+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import type { Web3Provider } from '@ethersproject/providers';
2+
import { OrderBookApi, MetadataApi, SupportedChainId } from '@cowprotocol/cow-sdk';
3+
import { EthersV5Adapter } from '@cowprotocol/sdk-ethers-v5-adapter';
4+
5+
export async function run(provider: Web3Provider): Promise<unknown> {
6+
const chainId = +(await provider.send('eth_chainId', []));
7+
if (chainId !== SupportedChainId.GNOSIS_CHAIN) {
8+
throw new Error(`Please connect to the Gnosis chain. ChainId: ${chainId}`);
9+
}
10+
11+
const signer = provider.getSigner();
12+
const adapter = new EthersV5Adapter({ provider, signer });
13+
14+
// Initialize packages individually
15+
const orderBookApi = new OrderBookApi({ chainId });
16+
const metadataApi = new MetadataApi(adapter);
17+
18+
try {
19+
// Test OrderBookApi
20+
const testOrderUid = '0x8464affce2df48b60f6976e51414dbc079e9c30ef64f4c1f78c7abe2c7f96a0c29104bb91ada737a89393c78335e48ff4708727e659523a1';
21+
const order = await orderBookApi.getOrder(testOrderUid);
22+
23+
// Test MetadataApi
24+
const appDataDoc = await metadataApi.generateAppDataDoc({
25+
appCode: 'Individual Basic Usage',
26+
environment: 'production',
27+
metadata: {
28+
quote: { slippageBips: 50 },
29+
orderClass: { orderClass: 'market' }
30+
}
31+
});
32+
const { appDataHex } = await metadataApi.getAppDataInfo(appDataDoc);
33+
34+
return {
35+
orderBook: {
36+
uid: order.uid.substring(0, 10) + '...',
37+
status: order.status
38+
},
39+
metadata: {
40+
appDataHex: appDataHex.substring(0, 10) + '...'
41+
}
42+
};
43+
} catch (error) {
44+
return {
45+
error: 'Test order not found, but packages initialized correctly'
46+
};
47+
}
48+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
---
2+
title: Advanced Usage
3+
---
4+
5+
Now that you understand the basics of individual packages, let's build a complete trading workflow. We'll use all three core packages together to create, quote, and sign an order.
6+
7+
## The Trading Workflow
8+
9+
We'll build the workflow in three steps:
10+
11+
1. Generate app data with `MetadataApi`
12+
2. Get a quote with `OrderBookApi`
13+
3. Sign the order with `OrderSigningUtils`
14+
15+
## Step 1: Generate App Data
16+
17+
First, we use `MetadataApi` to create order metadata:
18+
19+
```typescript
20+
/// file: run.ts
21+
import {
22+
OrderBookApi,
23+
MetadataApi,
24+
OrderSigningUtils,
25+
SupportedChainId,
26+
OrderQuoteSideKindSell,
27+
UnsignedOrder
28+
} from '@cowprotocol/cow-sdk';
29+
30+
export async function run(provider: Web3Provider): Promise<unknown> {
31+
const signer = provider.getSigner();
32+
const adapter = new EthersV5Adapter({ provider, signer });
33+
34+
// Initialize packages
35+
const metadataApi = new MetadataApi(adapter);
36+
37+
// Generate app data
38+
const appDataDoc = await metadataApi.generateAppDataDoc({
39+
appCode: 'Individual Packages Tutorial',
40+
environment: 'production',
41+
metadata: {
42+
referrer: { address: '0xcA771...' },
43+
quote: { slippageBips: 50 },
44+
orderClass: { orderClass: 'market' }
45+
}
46+
});
47+
48+
const { appDataHex, appDataContent } = await metadataApi.getAppDataInfo(appDataDoc);
49+
// ...
50+
}
51+
```
52+
53+
## Step 2: Get Quote
54+
55+
Next, we use `OrderBookApi` to get pricing information:
56+
57+
```typescript
58+
/// file: run.ts
59+
// Initialize OrderBookApi (no adapter needed)
60+
const orderBookApi = new OrderBookApi({ chainId });
61+
62+
// Get quote
63+
const { quote } = await orderBookApi.getQuote({
64+
sellToken: '0xe91d...', // wxDAI
65+
buyToken: '0x177...', // COW
66+
from: ownerAddress,
67+
receiver: ownerAddress,
68+
sellAmountBeforeFee: '1000000000000000000', // 1 wxDAI
69+
kind: OrderQuoteSideKindSell.SELL,
70+
appData: appDataContent,
71+
appDataHash: appDataHex
72+
});
73+
```
74+
75+
## Step 3: Sign Order
76+
77+
Finally, we use `OrderSigningUtils` to sign the order:
78+
79+
```typescript
80+
/// file: run.ts
81+
// Prepare order for signing
82+
const order: UnsignedOrder = {
83+
...quote,
84+
sellAmount: '1000000000000000000',
85+
feeAmount: '0',
86+
receiver: ownerAddress,
87+
appData: appDataHex
88+
};
89+
90+
// Sign using static method
91+
const signature = await OrderSigningUtils.signOrder(order, chainId, signer);
92+
```
93+
94+
## Complete Example
95+
96+
Here's the complete workflow putting it all together:
97+
98+
```typescript
99+
/// file: run.ts
100+
export async function run(provider: Web3Provider): Promise<unknown> {
101+
const signer = provider.getSigner();
102+
const adapter = new EthersV5Adapter({ provider, signer });
103+
104+
// Initialize packages
105+
const orderBookApi = new OrderBookApi({ chainId });
106+
const metadataApi = new MetadataApi(adapter);
107+
108+
try {
109+
// Step 1: App Data
110+
const appDataDoc = await metadataApi.generateAppDataDoc({...});
111+
const { appDataHex } = await metadataApi.getAppDataInfo(appDataDoc);
112+
113+
// Step 2: Quote
114+
const { quote } = await orderBookApi.getQuote({...});
115+
116+
// Step 3: Sign
117+
const order = { ...quote, appData: appDataHex, ... };
118+
const signature = await OrderSigningUtils.signOrder(order, chainId, signer);
119+
120+
return {
121+
appData: { appDataHex: appDataHex.substring(0, 10) + '...' },
122+
quote: {
123+
sellAmount: quote.sellAmount,
124+
buyAmount: quote.buyAmount
125+
},
126+
signature: {
127+
value: signature.signature.substring(0, 10) + '...',
128+
scheme: signature.signingScheme
129+
}
130+
};
131+
} catch (error) {
132+
return { error: error.message };
133+
}
134+
}
135+
```
136+
137+
## Run the Code
138+
139+
1. Accept the wallet connection request
140+
2. Press the "Run" button
141+
3. Observe the complete workflow execution
142+
143+
Example output:
144+
```json
145+
{
146+
"appData": {
147+
"appDataHex": "0xe269b..."
148+
},
149+
"quote": {
150+
"sellAmount": "1000000000000000000",
151+
"buyAmount": "400000000000000000000"
152+
},
153+
"signature": {
154+
"value": "0x98ac1...",
155+
"scheme": "eip712"
156+
}
157+
}
158+
```
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import type { Web3Provider } from '@ethersproject/providers';
2+
import {
3+
OrderBookApi,
4+
MetadataApi,
5+
OrderSigningUtils,
6+
SupportedChainId,
7+
OrderQuoteSideKindSell
8+
} from '@cowprotocol/cow-sdk';
9+
import { EthersV5Adapter } from '@cowprotocol/sdk-ethers-v5-adapter';
10+
11+
export async function run(provider: Web3Provider): Promise<unknown> {
12+
const chainId = +(await provider.send('eth_chainId', []));
13+
if (chainId !== SupportedChainId.GNOSIS_CHAIN) {
14+
throw new Error(`Please connect to the Gnosis chain. ChainId: ${chainId}`);
15+
}
16+
17+
const signer = provider.getSigner();
18+
const adapter = new EthersV5Adapter({ provider, signer });
19+
20+
// Initialize individual packages
21+
const orderBookApi = new OrderBookApi({ chainId });
22+
const metadataApi = new MetadataApi(adapter);
23+
24+
// TODO: Complete workflow using individual packages
25+
// 1. Generate app data with metadataApi
26+
// 2. Get quote with orderBookApi
27+
// 3. Sign order with OrderSigningUtils
28+
29+
return {};
30+
}

0 commit comments

Comments
 (0)