From 078e6869712ff5dbf3b9a091778c2df7d6c5c3d9 Mon Sep 17 00:00:00 2001 From: mfw78 Date: Fri, 5 Jan 2024 09:07:24 +0000 Subject: [PATCH] feat: appdata tutorials --- .../02-app-data/02-app-data/README.md | 5 - .../02-app-data/app-a/src/lib/run.ts | 27 ---- .../02-app-data/app-a/tsconfig.json | 15 -- .../00-getting-started-order}/README.md | 0 .../app-a/src/lib/run.ts | 0 .../app-b/src/lib/run.ts | 0 .../00-getting-started-order}/meta.json | 0 .../01-approve-sell-token-order}/README.md | 0 .../app-a/src/lib/run.ts | 0 .../app-b/src/lib/run.ts | 0 .../01-approve-sell-token-order}/meta.json | 0 .../01-order/02-quote-order}/README.md | 2 +- .../02-quote-order}/app-a/src/lib/run.ts | 0 .../02-quote-order}/app-b/src/lib/run.ts | 0 .../01-order/02-quote-order}/meta.json | 0 .../01-order/03-sign-order}/README.md | 2 +- .../03-sign-order}/app-a/src/lib/run.ts | 0 .../03-sign-order}/app-b/src/lib/run.ts | 0 .../01-order/03-sign-order}/meta.json | 0 .../01-order/04-submit-order}/README.md | 4 +- .../04-submit-order}/app-a/src/lib/run.ts | 0 .../04-submit-order}/app-b/src/lib/run.ts | 0 .../01-order/04-submit-order}/meta.json | 0 .../01-order/05-view-order}/README.md | 2 +- .../05-view-order}/app-a/src/lib/run.ts | 0 .../05-view-order}/app-b/src/lib/run.ts | 0 .../01-order/05-view-order}/meta.json | 0 .../06-cancel-off-chain-order}/README.md | 6 +- .../app-a/src/lib/run.ts | 0 .../app-b/src/lib/run.ts | 0 .../06-cancel-off-chain-order}/meta.json | 0 .../07-cancel-on-chain-order}/README.md | 0 .../app-a/src/lib/run.ts | 0 .../app-b/src/lib/run.ts | 0 .../07-cancel-on-chain-order}/meta.json | 0 .../01-order}/meta.json | 0 .../02-app-data/01-simple-app-data/README.md | 146 ++++++++++++++++++ .../01-simple-app-data/app-a/src/lib/run.ts | 5 + .../01-simple-app-data/app-b/src/lib/run.ts | 31 ++++ .../02-create-order-app-data/README.md | 81 ++++++++++ .../app-a/src/lib/run.ts | 83 ++++++++++ .../app-b/src/lib/run.ts | 86 +++++++++++ .../03-orderbook-upload-app-data/README.md | 51 ++++++ .../app-a/src/lib/run.ts | 34 ++++ .../app-b/src/lib/run.ts | 36 +++++ .../02-app-data/04-view-app-data/README.md | 83 ++++++++++ .../04-view-app-data/app-a/src/lib/run.ts | 6 + .../04-view-app-data/app-b/src/lib/run.ts | 14 ++ .../02-app-data/meta.json | 0 content/tutorial/01-simple-orders/meta.json | 8 + .../tsconfig.json | 0 .../01-eth-flow/01-create-eth-flow/README.md | 131 ++++++++++++++++ .../app-a/src/lib/GPv2Settlement.json | 0 .../app-a/src/lib/const.ts | 0 .../app-a/src/lib/getSafeSdkAndKit.ts | 0 .../01-create-eth-flow}/app-a/src/lib/run.ts | 0 .../01-create-eth-flow/app-b/src/lib/run.ts | 108 +++++++++++++ .../01-eth-flow/02-view-eth-flow/README.md | 5 + .../01-eth-flow/03-cancel-eth-flow/README.md | 5 + .../02-advanced-orders/01-eth-flow/meta.json | 8 + .../01-create-pre-signed-order}/README.md | 0 .../app-a/src/lib/GPv2Settlement.json | 20 +++ .../app-a/src/lib/const.ts | 12 ++ .../app-a/src/lib/getSafeSdkAndKit.ts | 28 ++++ .../app-a/src/lib/run.ts | 41 +++++ .../app-b/src/lib/run.ts | 0 .../02-view-pre-signed-order/README.md | 5 + .../03-cancel-pre-signed-order/README.md | 5 + .../02-pre-signed-orders/meta.json | 8 + .../03-hooks/01-app-data-hooks/README.md | 5 + .../03-hooks/02-pre-hooks/README.md | 5 + .../03-hooks/03-post-hooks/README.md | 5 + .../04-permit-and-bridge-hooks/README.md | 5 + .../03-hooks}/meta.json | 2 +- .../04-milkman/01-create-milkman/README.md | 5 + .../04-milkman/02-bot-milkman/README.md | 5 + .../04-milkman/03-cancel-milkman/README.md | 5 + .../04-milkman/04-triage-milkman/README.md | 7 + .../02-advanced-orders/04-milkman/meta.json | 8 + .../01-config-programmatic/README.md | 5 + .../02-create-programmatic/README.md | 5 + .../03-poll-programmatic/README.md | 5 + .../04-remove-programmatic/README.md | 5 + .../05-programmatic/05-merkle/README.md | 5 + .../05-programmatic/meta.json | 8 + .../meta.json | 0 .../tsconfig.json | 0 src/routes/+page.server.js | 2 +- src/routes/tutorial/+page.js | 2 +- src/routes/tutorial/[slug]/+page.server.js | 2 +- tests/env_file.spec.ts | 4 +- 91 files changed, 1137 insertions(+), 61 deletions(-) delete mode 100644 content/tutorial/01-orders/02-app-data/02-app-data/README.md delete mode 100644 content/tutorial/01-orders/02-app-data/02-app-data/app-a/src/lib/run.ts delete mode 100644 content/tutorial/01-orders/02-app-data/02-app-data/app-a/tsconfig.json rename content/tutorial/{01-orders/01-basic-orders/00-getting-started => 01-simple-orders/01-order/00-getting-started-order}/README.md (100%) rename content/tutorial/{01-orders/01-basic-orders/00-getting-started => 01-simple-orders/01-order/00-getting-started-order}/app-a/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/00-getting-started => 01-simple-orders/01-order/00-getting-started-order}/app-b/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/00-getting-started => 01-simple-orders/01-order/00-getting-started-order}/meta.json (100%) rename content/tutorial/{01-orders/01-basic-orders/01-approve => 01-simple-orders/01-order/01-approve-sell-token-order}/README.md (100%) rename content/tutorial/{01-orders/01-basic-orders/01-approve => 01-simple-orders/01-order/01-approve-sell-token-order}/app-a/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/01-approve => 01-simple-orders/01-order/01-approve-sell-token-order}/app-b/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/01-approve => 01-simple-orders/01-order/01-approve-sell-token-order}/meta.json (100%) rename content/tutorial/{01-orders/01-basic-orders/02-quote => 01-simple-orders/01-order/02-quote-order}/README.md (99%) rename content/tutorial/{01-orders/01-basic-orders/02-quote => 01-simple-orders/01-order/02-quote-order}/app-a/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/02-quote => 01-simple-orders/01-order/02-quote-order}/app-b/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/02-quote => 01-simple-orders/01-order/02-quote-order}/meta.json (100%) rename content/tutorial/{01-orders/01-basic-orders/03-sign => 01-simple-orders/01-order/03-sign-order}/README.md (96%) rename content/tutorial/{01-orders/01-basic-orders/03-sign => 01-simple-orders/01-order/03-sign-order}/app-a/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/03-sign => 01-simple-orders/01-order/03-sign-order}/app-b/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/03-sign => 01-simple-orders/01-order/03-sign-order}/meta.json (100%) rename content/tutorial/{01-orders/01-basic-orders/04-submit => 01-simple-orders/01-order/04-submit-order}/README.md (91%) rename content/tutorial/{01-orders/01-basic-orders/04-submit => 01-simple-orders/01-order/04-submit-order}/app-a/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/04-submit => 01-simple-orders/01-order/04-submit-order}/app-b/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/04-submit => 01-simple-orders/01-order/04-submit-order}/meta.json (100%) rename content/tutorial/{01-orders/01-basic-orders/07-view => 01-simple-orders/01-order/05-view-order}/README.md (97%) rename content/tutorial/{01-orders/01-basic-orders/07-view => 01-simple-orders/01-order/05-view-order}/app-a/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/07-view => 01-simple-orders/01-order/05-view-order}/app-b/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/07-view => 01-simple-orders/01-order/05-view-order}/meta.json (100%) rename content/tutorial/{01-orders/01-basic-orders/05-cancel-off-chain => 01-simple-orders/01-order/06-cancel-off-chain-order}/README.md (90%) rename content/tutorial/{01-orders/01-basic-orders/05-cancel-off-chain => 01-simple-orders/01-order/06-cancel-off-chain-order}/app-a/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/05-cancel-off-chain => 01-simple-orders/01-order/06-cancel-off-chain-order}/app-b/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/05-cancel-off-chain => 01-simple-orders/01-order/06-cancel-off-chain-order}/meta.json (100%) rename content/tutorial/{01-orders/01-basic-orders/06-cancel-on-chain => 01-simple-orders/01-order/07-cancel-on-chain-order}/README.md (100%) rename content/tutorial/{01-orders/01-basic-orders/06-cancel-on-chain => 01-simple-orders/01-order/07-cancel-on-chain-order}/app-a/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/06-cancel-on-chain => 01-simple-orders/01-order/07-cancel-on-chain-order}/app-b/src/lib/run.ts (100%) rename content/tutorial/{01-orders/01-basic-orders/06-cancel-on-chain => 01-simple-orders/01-order/07-cancel-on-chain-order}/meta.json (100%) rename content/tutorial/{01-orders/01-basic-orders => 01-simple-orders/01-order}/meta.json (100%) create mode 100644 content/tutorial/01-simple-orders/02-app-data/01-simple-app-data/README.md create mode 100644 content/tutorial/01-simple-orders/02-app-data/01-simple-app-data/app-a/src/lib/run.ts create mode 100644 content/tutorial/01-simple-orders/02-app-data/01-simple-app-data/app-b/src/lib/run.ts create mode 100644 content/tutorial/01-simple-orders/02-app-data/02-create-order-app-data/README.md create mode 100644 content/tutorial/01-simple-orders/02-app-data/02-create-order-app-data/app-a/src/lib/run.ts create mode 100644 content/tutorial/01-simple-orders/02-app-data/02-create-order-app-data/app-b/src/lib/run.ts create mode 100644 content/tutorial/01-simple-orders/02-app-data/03-orderbook-upload-app-data/README.md create mode 100644 content/tutorial/01-simple-orders/02-app-data/03-orderbook-upload-app-data/app-a/src/lib/run.ts create mode 100644 content/tutorial/01-simple-orders/02-app-data/03-orderbook-upload-app-data/app-b/src/lib/run.ts create mode 100644 content/tutorial/01-simple-orders/02-app-data/04-view-app-data/README.md create mode 100644 content/tutorial/01-simple-orders/02-app-data/04-view-app-data/app-a/src/lib/run.ts create mode 100644 content/tutorial/01-simple-orders/02-app-data/04-view-app-data/app-b/src/lib/run.ts rename content/tutorial/{01-orders => 01-simple-orders}/02-app-data/meta.json (100%) create mode 100644 content/tutorial/01-simple-orders/meta.json rename content/tutorial/{01-orders/03-advanced-orders => 01-simple-orders}/tsconfig.json (100%) create mode 100644 content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/README.md rename content/tutorial/{01-orders/03-advanced-orders/03-pre-signed-order => 02-advanced-orders/01-eth-flow/01-create-eth-flow}/app-a/src/lib/GPv2Settlement.json (100%) rename content/tutorial/{01-orders/03-advanced-orders/03-pre-signed-order => 02-advanced-orders/01-eth-flow/01-create-eth-flow}/app-a/src/lib/const.ts (100%) rename content/tutorial/{01-orders/03-advanced-orders/03-pre-signed-order => 02-advanced-orders/01-eth-flow/01-create-eth-flow}/app-a/src/lib/getSafeSdkAndKit.ts (100%) rename content/tutorial/{01-orders/03-advanced-orders/03-pre-signed-order => 02-advanced-orders/01-eth-flow/01-create-eth-flow}/app-a/src/lib/run.ts (100%) create mode 100644 content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/app-b/src/lib/run.ts create mode 100644 content/tutorial/02-advanced-orders/01-eth-flow/02-view-eth-flow/README.md create mode 100644 content/tutorial/02-advanced-orders/01-eth-flow/03-cancel-eth-flow/README.md create mode 100644 content/tutorial/02-advanced-orders/01-eth-flow/meta.json rename content/tutorial/{01-orders/03-advanced-orders/03-pre-signed-order => 02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order}/README.md (100%) create mode 100644 content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/GPv2Settlement.json create mode 100644 content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/const.ts create mode 100644 content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/getSafeSdkAndKit.ts create mode 100644 content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/run.ts rename content/tutorial/{01-orders/03-advanced-orders/03-pre-signed-order => 02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order}/app-b/src/lib/run.ts (100%) create mode 100644 content/tutorial/02-advanced-orders/02-pre-signed-orders/02-view-pre-signed-order/README.md create mode 100644 content/tutorial/02-advanced-orders/02-pre-signed-orders/03-cancel-pre-signed-order/README.md create mode 100644 content/tutorial/02-advanced-orders/02-pre-signed-orders/meta.json create mode 100644 content/tutorial/02-advanced-orders/03-hooks/01-app-data-hooks/README.md create mode 100644 content/tutorial/02-advanced-orders/03-hooks/02-pre-hooks/README.md create mode 100644 content/tutorial/02-advanced-orders/03-hooks/03-post-hooks/README.md create mode 100644 content/tutorial/02-advanced-orders/03-hooks/04-permit-and-bridge-hooks/README.md rename content/tutorial/{01-orders => 02-advanced-orders/03-hooks}/meta.json (81%) create mode 100644 content/tutorial/02-advanced-orders/04-milkman/01-create-milkman/README.md create mode 100644 content/tutorial/02-advanced-orders/04-milkman/02-bot-milkman/README.md create mode 100644 content/tutorial/02-advanced-orders/04-milkman/03-cancel-milkman/README.md create mode 100644 content/tutorial/02-advanced-orders/04-milkman/04-triage-milkman/README.md create mode 100644 content/tutorial/02-advanced-orders/04-milkman/meta.json create mode 100644 content/tutorial/02-advanced-orders/05-programmatic/01-config-programmatic/README.md create mode 100644 content/tutorial/02-advanced-orders/05-programmatic/02-create-programmatic/README.md create mode 100644 content/tutorial/02-advanced-orders/05-programmatic/03-poll-programmatic/README.md create mode 100644 content/tutorial/02-advanced-orders/05-programmatic/04-remove-programmatic/README.md create mode 100644 content/tutorial/02-advanced-orders/05-programmatic/05-merkle/README.md create mode 100644 content/tutorial/02-advanced-orders/05-programmatic/meta.json rename content/tutorial/{01-orders/03-advanced-orders => 02-advanced-orders}/meta.json (100%) rename content/tutorial/{01-orders => 02-advanced-orders}/tsconfig.json (100%) diff --git a/content/tutorial/01-orders/02-app-data/02-app-data/README.md b/content/tutorial/01-orders/02-app-data/02-app-data/README.md deleted file mode 100644 index 89b8963..0000000 --- a/content/tutorial/01-orders/02-app-data/02-app-data/README.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: App data ---- - -App data generation diff --git a/content/tutorial/01-orders/02-app-data/02-app-data/app-a/src/lib/run.ts b/content/tutorial/01-orders/02-app-data/02-app-data/app-a/src/lib/run.ts deleted file mode 100644 index 5c6f7f9..0000000 --- a/content/tutorial/01-orders/02-app-data/02-app-data/app-a/src/lib/run.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { Web3Provider } from '@ethersproject/providers' -import { MetadataApi } from '@cowprotocol/app-data' - -export async function run(provider: Web3Provider): Promise { - const metadataApi = new MetadataApi() - - const appCode = '' - const environment = 'prod' - const referrer = { address: `0x360Ba61Bc799edfa01e306f1eCCb2F6e0C3C8c8e` } - - const quote = { slippageBips: '0' } // Slippage percent, it's 0 to 100 - const orderClass = { orderClass: 'limit' } // "market" | "limit" | "liquidity" - - const appDataDoc = await metadataApi.generateAppDataDoc({ - appCode, - environment, - metadata: { - referrer, - quote, - orderClass - }, - }) - - const { cid, appDataHex, appDataContent } = await metadataApi.appDataToCid(appDataDoc) - - return { appDataDoc, cid, appDataHex, appDataContent } -} diff --git a/content/tutorial/01-orders/02-app-data/02-app-data/app-a/tsconfig.json b/content/tutorial/01-orders/02-app-data/02-app-data/app-a/tsconfig.json deleted file mode 100644 index ebe331b..0000000 --- a/content/tutorial/01-orders/02-app-data/02-app-data/app-a/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "../../../../common/tsconfig.json", - "compilerOptions": { - "baseUrl": ".", - "paths": { - "*": [ - "../../../../common/*", - "../../../../common/node_modules/*" - ] - } - }, - "include": [ - "**/*" // Include all files in app-a - ] -} diff --git a/content/tutorial/01-orders/01-basic-orders/00-getting-started/README.md b/content/tutorial/01-simple-orders/01-order/00-getting-started-order/README.md similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/00-getting-started/README.md rename to content/tutorial/01-simple-orders/01-order/00-getting-started-order/README.md diff --git a/content/tutorial/01-orders/01-basic-orders/00-getting-started/app-a/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/00-getting-started-order/app-a/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/00-getting-started/app-a/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/00-getting-started-order/app-a/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/00-getting-started/app-b/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/00-getting-started-order/app-b/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/00-getting-started/app-b/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/00-getting-started-order/app-b/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/00-getting-started/meta.json b/content/tutorial/01-simple-orders/01-order/00-getting-started-order/meta.json similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/00-getting-started/meta.json rename to content/tutorial/01-simple-orders/01-order/00-getting-started-order/meta.json diff --git a/content/tutorial/01-orders/01-basic-orders/01-approve/README.md b/content/tutorial/01-simple-orders/01-order/01-approve-sell-token-order/README.md similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/01-approve/README.md rename to content/tutorial/01-simple-orders/01-order/01-approve-sell-token-order/README.md diff --git a/content/tutorial/01-orders/01-basic-orders/01-approve/app-a/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/01-approve-sell-token-order/app-a/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/01-approve/app-a/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/01-approve-sell-token-order/app-a/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/01-approve/app-b/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/01-approve-sell-token-order/app-b/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/01-approve/app-b/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/01-approve-sell-token-order/app-b/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/01-approve/meta.json b/content/tutorial/01-simple-orders/01-order/01-approve-sell-token-order/meta.json similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/01-approve/meta.json rename to content/tutorial/01-simple-orders/01-order/01-approve-sell-token-order/meta.json diff --git a/content/tutorial/01-orders/01-basic-orders/02-quote/README.md b/content/tutorial/01-simple-orders/01-order/02-quote-order/README.md similarity index 99% rename from content/tutorial/01-orders/01-basic-orders/02-quote/README.md rename to content/tutorial/01-simple-orders/01-order/02-quote-order/README.md index 71e6aa5..f35f3c2 100644 --- a/content/tutorial/01-orders/01-basic-orders/02-quote/README.md +++ b/content/tutorial/01-simple-orders/01-order/02-quote-order/README.md @@ -157,4 +157,4 @@ In the above case, we can see that: - the `feeAmount` is `1881812051493698` atomic units of `wxDAI` (which is `0.001881812051493698` `wxDAI`) - the `kind` is `sell` -The above `OrderQuoteResponse` object actually maps to the [`GPv2Order.Data`](https://beta.docs.cow.fi/cow-protocol/reference/contracts/core/settlement#gpv2orderdata-struct) struct for the smart contract, so this is what we will sign in the [next tutorial](/tutorial/sign) for our swap. \ No newline at end of file +The above `OrderQuoteResponse` object actually maps to the [`GPv2Order.Data`](https://beta.docs.cow.fi/cow-protocol/reference/contracts/core/settlement#gpv2orderdata-struct) struct for the smart contract, so this is what we will sign in the [next tutorial](/tutorial/sign-order) for our swap. \ No newline at end of file diff --git a/content/tutorial/01-orders/01-basic-orders/02-quote/app-a/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/02-quote-order/app-a/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/02-quote/app-a/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/02-quote-order/app-a/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/02-quote/app-b/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/02-quote-order/app-b/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/02-quote/app-b/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/02-quote-order/app-b/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/02-quote/meta.json b/content/tutorial/01-simple-orders/01-order/02-quote-order/meta.json similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/02-quote/meta.json rename to content/tutorial/01-simple-orders/01-order/02-quote-order/meta.json diff --git a/content/tutorial/01-orders/01-basic-orders/03-sign/README.md b/content/tutorial/01-simple-orders/01-order/03-sign-order/README.md similarity index 96% rename from content/tutorial/01-orders/01-basic-orders/03-sign/README.md rename to content/tutorial/01-simple-orders/01-order/03-sign-order/README.md index 7822b09..5938bfb 100644 --- a/content/tutorial/01-orders/01-basic-orders/03-sign/README.md +++ b/content/tutorial/01-simple-orders/01-order/03-sign-order/README.md @@ -2,7 +2,7 @@ title: Signing --- -Here we will build on the previous tutorial and sign the quote we got from the [quote tutorial](/tutorial/quote), so that we can place an order on CoW Protocol. +Here we will build on the previous tutorial and sign the quote we got from the [quote tutorial](/tutorial/quote-order), so that we can place an order on CoW Protocol. ## Intents and signatures diff --git a/content/tutorial/01-orders/01-basic-orders/03-sign/app-a/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/03-sign-order/app-a/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/03-sign/app-a/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/03-sign-order/app-a/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/03-sign/app-b/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/03-sign-order/app-b/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/03-sign/app-b/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/03-sign-order/app-b/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/03-sign/meta.json b/content/tutorial/01-simple-orders/01-order/03-sign-order/meta.json similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/03-sign/meta.json rename to content/tutorial/01-simple-orders/01-order/03-sign-order/meta.json diff --git a/content/tutorial/01-orders/01-basic-orders/04-submit/README.md b/content/tutorial/01-simple-orders/01-order/04-submit-order/README.md similarity index 91% rename from content/tutorial/01-orders/01-basic-orders/04-submit/README.md rename to content/tutorial/01-simple-orders/01-order/04-submit-order/README.md index b07df18..5ebe782 100644 --- a/content/tutorial/01-orders/01-basic-orders/04-submit/README.md +++ b/content/tutorial/01-simple-orders/01-order/04-submit-order/README.md @@ -2,7 +2,7 @@ title: Submitting --- -Further building on the previous tutorial, we will now submit the order we signed in the [sign order tutorial](/tutorial/sign) to CoW Protocol. +Further building on the previous tutorial, we will now submit the order we signed in the [sign order tutorial](/tutorial/sign-order) to CoW Protocol. ## Submitting an order @@ -58,4 +58,4 @@ An example `orderId` should look like: A couple of errors may easily result when running this code: - **`InsufficientBalance`**: The wallet you have signed with does not have enough balance for the `sellToken`. A reminder in this example, the `sellToken` is `wxDai` on Gnosis chain. -- **`InsufficientAllowance`**: In this case, the wallet has enough balance, however you have missed out a step in the [approve tutorial](/tutorial/approve) and have not approved the `relayerAddress` to spend the `sellToken` on your behalf. +- **`InsufficientAllowance`**: In this case, the wallet has enough balance, however you have missed out a step in the [approve tutorial](/tutorial/approve-sell-token-order) and have not approved the `relayerAddress` to spend the `sellToken` on your behalf. diff --git a/content/tutorial/01-orders/01-basic-orders/04-submit/app-a/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/04-submit-order/app-a/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/04-submit/app-a/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/04-submit-order/app-a/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/04-submit/app-b/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/04-submit-order/app-b/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/04-submit/app-b/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/04-submit-order/app-b/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/04-submit/meta.json b/content/tutorial/01-simple-orders/01-order/04-submit-order/meta.json similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/04-submit/meta.json rename to content/tutorial/01-simple-orders/01-order/04-submit-order/meta.json diff --git a/content/tutorial/01-orders/01-basic-orders/07-view/README.md b/content/tutorial/01-simple-orders/01-order/05-view-order/README.md similarity index 97% rename from content/tutorial/01-orders/01-basic-orders/07-view/README.md rename to content/tutorial/01-simple-orders/01-order/05-view-order/README.md index 2c113a6..ada37e5 100644 --- a/content/tutorial/01-orders/01-basic-orders/07-view/README.md +++ b/content/tutorial/01-simple-orders/01-order/05-view-order/README.md @@ -10,7 +10,7 @@ With CoW Protocol, the only way to view the status of an order that has not yet ## Instantiate the SDK -We will start from the basic setup from the [quote tutorial](/tutorial/quote) after we have instantiated the `OrderBookApi`. +We will start from the basic setup from the [quote tutorial](/tutorial/quote-order) after we have instantiated the `OrderBookApi`. ### Query parameters diff --git a/content/tutorial/01-orders/01-basic-orders/07-view/app-a/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/05-view-order/app-a/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/07-view/app-a/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/05-view-order/app-a/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/07-view/app-b/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/05-view-order/app-b/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/07-view/app-b/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/05-view-order/app-b/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/07-view/meta.json b/content/tutorial/01-simple-orders/01-order/05-view-order/meta.json similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/07-view/meta.json rename to content/tutorial/01-simple-orders/01-order/05-view-order/meta.json diff --git a/content/tutorial/01-orders/01-basic-orders/05-cancel-off-chain/README.md b/content/tutorial/01-simple-orders/01-order/06-cancel-off-chain-order/README.md similarity index 90% rename from content/tutorial/01-orders/01-basic-orders/05-cancel-off-chain/README.md rename to content/tutorial/01-simple-orders/01-order/06-cancel-off-chain-order/README.md index 9205f60..4bc87dd 100644 --- a/content/tutorial/01-orders/01-basic-orders/05-cancel-off-chain/README.md +++ b/content/tutorial/01-simple-orders/01-order/06-cancel-off-chain-order/README.md @@ -12,7 +12,7 @@ To cancel an order, we need to know the `orderUid` of the order we want to cance ### Instantiate the SDK -We will start from the basic setup from the [quote tutorial](/tutorial/quote) after we have instantiated the `OrderBookApi` and configured the `signer`. +We will start from the basic setup from the [quote tutorial](/tutorial/quote-order) after we have instantiated the `OrderBookApi` and configured the `signer`. ### Cancellation parameters @@ -36,7 +36,7 @@ export async function run(provider: Web3Provider): Promise { ### Signing the cancellation -Just like we did in the [sign order tutorial](/tutorial/sign), we need to sign the cancellation. To do this, we will use the `OrderSigningUtils` utility. +Just like we did in the [sign order tutorial](/tutorial/sign-order), we need to sign the cancellation. To do this, we will use the `OrderSigningUtils` utility. ```typescript /// file: run.ts @@ -83,7 +83,7 @@ export async function run(provider: Web3Provider): Promise { } ``` -Just as we did in the [submit order tutorial](/tutorial/submit), we are using a `try/catch` block to handle errors. +Just as we did in the [submit order tutorial](/tutorial/submit-order), we are using a `try/catch` block to handle errors. ## Run the code diff --git a/content/tutorial/01-orders/01-basic-orders/05-cancel-off-chain/app-a/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/06-cancel-off-chain-order/app-a/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/05-cancel-off-chain/app-a/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/06-cancel-off-chain-order/app-a/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/05-cancel-off-chain/app-b/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/06-cancel-off-chain-order/app-b/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/05-cancel-off-chain/app-b/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/06-cancel-off-chain-order/app-b/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/05-cancel-off-chain/meta.json b/content/tutorial/01-simple-orders/01-order/06-cancel-off-chain-order/meta.json similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/05-cancel-off-chain/meta.json rename to content/tutorial/01-simple-orders/01-order/06-cancel-off-chain-order/meta.json diff --git a/content/tutorial/01-orders/01-basic-orders/06-cancel-on-chain/README.md b/content/tutorial/01-simple-orders/01-order/07-cancel-on-chain-order/README.md similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/06-cancel-on-chain/README.md rename to content/tutorial/01-simple-orders/01-order/07-cancel-on-chain-order/README.md diff --git a/content/tutorial/01-orders/01-basic-orders/06-cancel-on-chain/app-a/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/07-cancel-on-chain-order/app-a/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/06-cancel-on-chain/app-a/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/07-cancel-on-chain-order/app-a/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/06-cancel-on-chain/app-b/src/lib/run.ts b/content/tutorial/01-simple-orders/01-order/07-cancel-on-chain-order/app-b/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/06-cancel-on-chain/app-b/src/lib/run.ts rename to content/tutorial/01-simple-orders/01-order/07-cancel-on-chain-order/app-b/src/lib/run.ts diff --git a/content/tutorial/01-orders/01-basic-orders/06-cancel-on-chain/meta.json b/content/tutorial/01-simple-orders/01-order/07-cancel-on-chain-order/meta.json similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/06-cancel-on-chain/meta.json rename to content/tutorial/01-simple-orders/01-order/07-cancel-on-chain-order/meta.json diff --git a/content/tutorial/01-orders/01-basic-orders/meta.json b/content/tutorial/01-simple-orders/01-order/meta.json similarity index 100% rename from content/tutorial/01-orders/01-basic-orders/meta.json rename to content/tutorial/01-simple-orders/01-order/meta.json diff --git a/content/tutorial/01-simple-orders/02-app-data/01-simple-app-data/README.md b/content/tutorial/01-simple-orders/02-app-data/01-simple-app-data/README.md new file mode 100644 index 0000000..03ffa87 --- /dev/null +++ b/content/tutorial/01-simple-orders/02-app-data/01-simple-app-data/README.md @@ -0,0 +1,146 @@ +--- +title: Simple app data +--- + +So, we have created a simple order in the previous section, but what if you're a wallet provider, and you want to add some extra data to the order? For example, you may want to associate the order with your app in order to brag about how many orders on CoW Protocol are created by your app. + +## `app-data` SDK + +The `app-data` is documented in [JSON Schema](https://beta.docs.cow.fi/cow-protocol/reference/core/intents/app-data#schema). Writing to a schema is not very convenient, so we have a special SDK for that. It's called the `app-data` SDK. + +To install it, run: `npm install @cowprotocol/app-data` + +> It is highly suggested to use the `app-data` SDK to generate the `app-data` document. There are many subtle nuances to the `app-data` document, making it easy to get wrong. + +### Instantiate the SDK + +To instantiate the SDK, we simply call it's constructor: + +```typescript +/// file: run.ts +import type { Web3Provider } from '@ethersproject/providers'; ++++import { MetadataApi } from '@cowprotocol/app-data';+++ + +export async function run(provider: Web3Provider): Promise { + // ... + const metadataApi = new MetadataApi(); + // ... +} +``` + +### App data parameters + +As an example, if we were developing a wallet, we may want to add some metadata to the order. In doing so, we will provide: + +- `appCode` - the name of our app +- `environment` - the environment we're running on (e.g. `prod`, `staging`) +- `referrer` - the ethereum address for the referrer of the order +- `quote` - the quote parameters, nominally the slippage applied to the order +- `orderClass` - the order class, eg. `market`, `limit`, `twap` etc. + +```typescript +/// file: run.ts +import type { Web3Provider } from '@ethersproject/providers'; ++++import { MetadataApi, latest } from '@cowprotocol/app-data';+++ + +export async function run(provider: Web3Provider): Promise { + // ... + + const appCode = 'Decentralized CoW'; + const environment = 'prod'; + const referrer = { address: '0xcA771eda0c70aA7d053aB1B25004559B918FE662' }; + + const quoteAppDoc: latest.Quote = { slippageBips: '50' }; + const orderClass: latest.OrderClass = { orderClass: 'market' }; + + // ... +} +``` + +> We use the `latest` namespace to get the latest types. The schema is versioned, so you may alternatively use the version namespace. + +### App data document + +Now that we have the parameters, we can create the app data document: + +```typescript +/// file: run.ts +import type { Web3Provider } from '@ethersproject/providers'; +import { MetadataApi, latest } from '@cowprotocol/app-data'; + +export async function run(provider: Web3Provider): Promise { + // ... + + const appDataDoc = await metadataApi.generateAppDataDoc({ + appCode, + environment, + metadata: { + referrer, + quote: quoteAppDoc, + orderClass, + }, + }); + + // ... +} +``` + +### Processing the document + +Now that we have the document, we can process it. In doing this, we will: + +- determine the CID of the document +- determine the appDataContent, which is passed in the order's `appData` field when sent to the API +- determine the appDataHex, which is passed in the order's `appDataHash` field when sent to the API + +```typescript +/// file: run.ts +import type { Web3Provider } from '@ethersproject/providers'; +import { MetadataApi, latest } from '@cowprotocol/app-data'; + +export async function run(provider: Web3Provider): Promise { + // ... + + const { appDataHex, appDataContent } = await metadataApi.appDataToCid(appDataDoc); + + return { + appDataDoc, + appDataHex, + appDataContent, + }; +} +``` + +## Run the code + +To run the code, we can press the "Run" button in the bottom right panel (the web container). + +1. Press the "Run" button +2. Observe the respective data returned to the output panel + +An example output should look like: + +```json +/// file: output.json +{ + "appDataDoc": { + "appCode": "Decentralized CoW", + "metadata": { + "referrer": { + "address": "0xcA771eda0c70aA7d053aB1B25004559B918FE662" + }, + "quote": { + "slippageBips": "50" + }, + "orderClass": { + "orderClass": "market" + } + }, + "version": "0.11.0", + "environment": "prod" + }, + "cid": "f01551b20b4b4561d26cfe084594ddbb4cf6af5397c1bf1cb31997ae4d2a82325eeda8f6d", + "appDataHex": "0xb4b4561d26cfe084594ddbb4cf6af5397c1bf1cb31997ae4d2a82325eeda8f6d", + "appDataContent": "{\"appCode\":\"Decentralized CoW\",\"environment\":\"prod\",\"metadata\":{\"orderClass\":{\"orderClass\":\"market\"},\"quote\":{\"slippageBips\":\"50\"},\"referrer\":{\"address\":\"0xcA771eda0c70aA7d053aB1B25004559B918FE662\"}},\"version\":\"0.11.0\"}" +} +``` \ No newline at end of file diff --git a/content/tutorial/01-simple-orders/02-app-data/01-simple-app-data/app-a/src/lib/run.ts b/content/tutorial/01-simple-orders/02-app-data/01-simple-app-data/app-a/src/lib/run.ts new file mode 100644 index 0000000..2e28bcb --- /dev/null +++ b/content/tutorial/01-simple-orders/02-app-data/01-simple-app-data/app-a/src/lib/run.ts @@ -0,0 +1,5 @@ +import type { Web3Provider } from '@ethersproject/providers' + +export async function run(provider: Web3Provider): Promise { + // TODO: Implement +} diff --git a/content/tutorial/01-simple-orders/02-app-data/01-simple-app-data/app-b/src/lib/run.ts b/content/tutorial/01-simple-orders/02-app-data/01-simple-app-data/app-b/src/lib/run.ts new file mode 100644 index 0000000..05bd261 --- /dev/null +++ b/content/tutorial/01-simple-orders/02-app-data/01-simple-app-data/app-b/src/lib/run.ts @@ -0,0 +1,31 @@ +import type { Web3Provider } from '@ethersproject/providers' +import { MetadataApi, latest } from '@cowprotocol/app-data' + +export async function run(provider: Web3Provider): Promise { + 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) + + return { + appDataDoc, + appDataHex, + appDataContent + } +} diff --git a/content/tutorial/01-simple-orders/02-app-data/02-create-order-app-data/README.md b/content/tutorial/01-simple-orders/02-app-data/02-create-order-app-data/README.md new file mode 100644 index 0000000..5624f56 --- /dev/null +++ b/content/tutorial/01-simple-orders/02-app-data/02-create-order-app-data/README.md @@ -0,0 +1,81 @@ +--- +title: Create order with appData +--- + +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: + +- [Submit order](/tutorial/submit-order) +- [Simple app data](/tutorial/simple-app-data) + +## Instantiate the SDK + +We will start from the basic setup from the [submit order](/tutorial/submit-order) tutorial and the [simple app data](/tutorial/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 it's has (`appDataHex`) +- wrap the app data into the response object +- determine any additional fees that may be required (if the app data document contains hooks) + +```typescript +/// file: run.ts +// ... +export async function run(provider: Web3Provider): Promise { + // ... + + 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. + +```typescript +/// file: run.ts +// ... +export async function run(provider: Web3Provider): Promise { + // ... + 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. + +1. Accept the connection request in Rabby +2. Press the "Run" button again +3. Observe the `orderId` returned to the output panel + +You can now use the `orderId` to check the status of the order on [CoW Explorer](https://explorer.cow.fi/). 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/submit-order) tutorial may occur. In addition, the following errors may occur: + +- **`InvalidAppData`**: The app data passed to the API is not either `bytes32` or a stringified JSON object. +- **`AppDataHashMismatch`**: The hash of the app data document doesn't match the `appDataHash` field provided in the order. This may be due to the app data document being modified after the order was signed. diff --git a/content/tutorial/01-simple-orders/02-app-data/02-create-order-app-data/app-a/src/lib/run.ts b/content/tutorial/01-simple-orders/02-app-data/02-create-order-app-data/app-a/src/lib/run.ts new file mode 100644 index 0000000..9294a3c --- /dev/null +++ b/content/tutorial/01-simple-orders/02-app-data/02-create-order-app-data/app-a/src/lib/run.ts @@ -0,0 +1,83 @@ +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 { + 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 + } +} diff --git a/content/tutorial/01-simple-orders/02-app-data/02-create-order-app-data/app-b/src/lib/run.ts b/content/tutorial/01-simple-orders/02-app-data/02-create-order-app-data/app-b/src/lib/run.ts new file mode 100644 index 0000000..d3d4842 --- /dev/null +++ b/content/tutorial/01-simple-orders/02-app-data/02-create-order-app-data/app-b/src/lib/run.ts @@ -0,0 +1,86 @@ +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 { + 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, + appData: appDataContent, + appDataHash: appDataHex, + }; + + const { quote } = await orderBookApi.getQuote(quoteRequest); + + const order: UnsignedOrder = { + ...quote, + receiver: ownerAddress, + appData: appDataHex, + } + + 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 + } +} diff --git a/content/tutorial/01-simple-orders/02-app-data/03-orderbook-upload-app-data/README.md b/content/tutorial/01-simple-orders/02-app-data/03-orderbook-upload-app-data/README.md new file mode 100644 index 0000000..4ad05dc --- /dev/null +++ b/content/tutorial/01-simple-orders/02-app-data/03-orderbook-upload-app-data/README.md @@ -0,0 +1,51 @@ +--- +title: Upload to the API +--- + +In the last tutorial we showed how to create an order with app data. There are however times when you may want to create an order but you do not have access at that time to the extended app data document, i.e. you only have the **hash** of the `appData`. + +A concrete example of this is if you are using a programmatic order, where the `appData` hash is stored in the contract and/or passed back to a watch-tower for execution. In this case, the watch-tower may not have access to the extended app data document, but it does have access to the hash. To allow for this case, we can upload the app data to the Order Book API before the watch-tower relays the order to the Order Book API. + +## Instantiate the SDK + +We will start from the basic setup from the [quote order](/tutorial/quote-order) tutorial and the [simple app data](/tutorial/simple-app-data) tutorial. This has been populated in the code editor for you. + +### Uploading the app data + +To upload the app data using the Order Book API, we simply use the handy `OrderBookApi` class. This class has a `uploadAppData` method which takes the `appData` hash and returns the `appData` document. + +```typescript +/// file: run.ts +import type { Web3Provider } from '@ethersproject/providers'; +import { MetadataApi, latest } from '@cowprotocol/app-data'; +import { OrderBookApi, SupportedChainId } from '@cowprotocol/cow-sdk' + +export async function run(provider: Web3Provider): Promise { + // ... + const { appDataHex, appDataContent } = await metadataApi.appDataToCid(appDataDoc); + + +++const fullAppData = await orderBookApi.uploadAppData(appDataHex, appDataContent);+++ + + return { fullAppData } +} +``` + +> Despite the name, `fullAppData` is actually just the **appData hash** that is returned from the API. + +## Run the code + +To run the code, we can press the "Run" button in the bottom right panel (the web container). + +1. Press the "Run" button +2. Observe the respective data returned to the output panel + +An example output should look like: + +```json +/// file: output.json +{ + "fullAppData": "0xe63428d06deb873ea243dc8fee366c3ef51933770e6c5e121669ed78deaf6a5e" +} +``` + +Therefore, if we were to sign manually (or via a contract), for the `appData` field we could use `0xe63428d06deb873ea243dc8fee366c3ef51933770e6c5e121669ed78deaf6a5e`. diff --git a/content/tutorial/01-simple-orders/02-app-data/03-orderbook-upload-app-data/app-a/src/lib/run.ts b/content/tutorial/01-simple-orders/02-app-data/03-orderbook-upload-app-data/app-a/src/lib/run.ts new file mode 100644 index 0000000..e3c7747 --- /dev/null +++ b/content/tutorial/01-simple-orders/02-app-data/03-orderbook-upload-app-data/app-a/src/lib/run.ts @@ -0,0 +1,34 @@ +import type { Web3Provider } from '@ethersproject/providers' +import { MetadataApi, latest } from '@cowprotocol/app-data' +import { OrderBookApi, SupportedChainId } from '@cowprotocol/cow-sdk' + +export async function run(provider: Web3Provider): Promise { + 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) + + return { appDataDoc, appDataHex, appDataContent } +} diff --git a/content/tutorial/01-simple-orders/02-app-data/03-orderbook-upload-app-data/app-b/src/lib/run.ts b/content/tutorial/01-simple-orders/02-app-data/03-orderbook-upload-app-data/app-b/src/lib/run.ts new file mode 100644 index 0000000..424f382 --- /dev/null +++ b/content/tutorial/01-simple-orders/02-app-data/03-orderbook-upload-app-data/app-b/src/lib/run.ts @@ -0,0 +1,36 @@ +import type { Web3Provider } from '@ethersproject/providers' +import { MetadataApi, latest } from '@cowprotocol/app-data' +import { OrderBookApi, SupportedChainId } from '@cowprotocol/cow-sdk' + +export async function run(provider: Web3Provider): Promise { + 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 fullAppData = await orderBookApi.uploadAppData(appDataHex, appDataContent); + + return { fullAppData } +} diff --git a/content/tutorial/01-simple-orders/02-app-data/04-view-app-data/README.md b/content/tutorial/01-simple-orders/02-app-data/04-view-app-data/README.md new file mode 100644 index 0000000..eecd83b --- /dev/null +++ b/content/tutorial/01-simple-orders/02-app-data/04-view-app-data/README.md @@ -0,0 +1,83 @@ +--- +title: Retrieve by appData hash +--- + +As with most things in the Order Book API, we can also view the app data that we have uploaded. This is done via the `getAppData` method on the `OrderBookApi` class. + +Let's consider that we are browsing [CoW Explorer](https://explorer.cow.fi) and have come across an [order on *Gnosis Chain*](https://explorer.cow.fi/gc/orders/0x87ab37ea7d198aca414a0c1446aeba41e97be6c0c814ebe2b7005926dce09d26c40b42e0b02191b4ca09d6ed846abe578159fe5f6597f5b2): + +```json +/// file: order.json +{ + "orderuId": "0x87ab37ea7d198aca414a0c1446aeba41e97be6c0c814ebe2b7005926dce09d26c40b42e0b02191b4ca09d6ed846abe578159fe5f6597f5b2", +} +``` + +Even though the CoW Explorer shows the extended app data document, for the sake of the tutorial let's assume that we do not have access to this document. Instead, we can use the `getAppData` method to retrieve the app data document from the Order Book API. + +## Instantiate the SDK + +We will start from a basic setup with the `OrderBookApi` class already instantiated. This has been populated in the code editor for you. + +### Retrieving the app data + +When looking at the order on CoW Explorer, we can see that the `appData` **hash** is `0x462ed5aa08a031342e30dcd1bc374da7ca9be2800ca7a87e43590880aa034554`. + +We assign this to a variable and use it to query the Order Book API for the app data document. + +```typescript +/// file: run.ts +import type { Web3Provider } from '@ethersproject/providers'; +import { OrderBookApi, SupportedChainId } from '@cowprotocol/cow-sdk' + +export async function run(provider: Web3Provider): Promise { + // ... + +++const appDataHash = '0x462ed5aa08a031342e30dcd1bc374da7ca9be2800ca7a87e43590880aa034554';+++ + + +++const appDataDoc = await orderBookApi.getAppData(appDataHash);+++ +} +``` + +### Prettifying the output + +The `appDataDoc` is a JSON object, that contains the `fullAppData` field, which in itself is simply the `appDataDoc` stringified. We can now interpret this using `JSON.parse` and `JSON.stringify` to prettify the output. + +```typescript +/// file: run.ts +import type { Web3Provider } from '@ethersproject/providers'; +import { OrderBookApi, SupportedChainId } from '@cowprotocol/cow-sdk' + +export async function run(provider: Web3Provider): Promise { + // ... + + +++const fullAppData = JSON.parse(appDataDoc.fullAppData);+++ + + return fullAppData; +} +``` + +## Run the code + +To run the code, we can press the "Run" button in the bottom right panel (the web container). + +1. Press the "Run" button +2. Observe the respective data returned to the output panel + +An example output should look like: + +```json +/// file: output.json +{ + "appCode": "CoW Swap-SafeApp", + "environment": "production", + "metadata": { + "orderClass": { + "orderClass": "twap" + }, + "quote": { + "slippageBips": "7500" + } + }, + "version": "0.11.0" +} +``` \ No newline at end of file diff --git a/content/tutorial/01-simple-orders/02-app-data/04-view-app-data/app-a/src/lib/run.ts b/content/tutorial/01-simple-orders/02-app-data/04-view-app-data/app-a/src/lib/run.ts new file mode 100644 index 0000000..54c4df7 --- /dev/null +++ b/content/tutorial/01-simple-orders/02-app-data/04-view-app-data/app-a/src/lib/run.ts @@ -0,0 +1,6 @@ +import type { Web3Provider } from '@ethersproject/providers' +import { OrderBookApi, SupportedChainId } from '@cowprotocol/cow-sdk' + +export async function run(provider: Web3Provider): Promise { + const orderBookApi = new OrderBookApi({ chainId: SupportedChainId.GNOSIS_CHAIN }); +} diff --git a/content/tutorial/01-simple-orders/02-app-data/04-view-app-data/app-b/src/lib/run.ts b/content/tutorial/01-simple-orders/02-app-data/04-view-app-data/app-b/src/lib/run.ts new file mode 100644 index 0000000..62a3d29 --- /dev/null +++ b/content/tutorial/01-simple-orders/02-app-data/04-view-app-data/app-b/src/lib/run.ts @@ -0,0 +1,14 @@ +import type { Web3Provider } from '@ethersproject/providers' +import { OrderBookApi, SupportedChainId } from '@cowprotocol/cow-sdk' + +export async function run(provider: Web3Provider): Promise { + const orderBookApi = new OrderBookApi({ chainId: SupportedChainId.GNOSIS_CHAIN }); + + const appDataHash = '0x462ed5aa08a031342e30dcd1bc374da7ca9be2800ca7a87e43590880aa034554'; + + const appDataDoc = await orderBookApi.getAppData(appDataHash); + + const fullAppData = JSON.parse(appDataDoc.fullAppData) + + return fullAppData; +} diff --git a/content/tutorial/01-orders/02-app-data/meta.json b/content/tutorial/01-simple-orders/02-app-data/meta.json similarity index 100% rename from content/tutorial/01-orders/02-app-data/meta.json rename to content/tutorial/01-simple-orders/02-app-data/meta.json diff --git a/content/tutorial/01-simple-orders/meta.json b/content/tutorial/01-simple-orders/meta.json new file mode 100644 index 0000000..342567f --- /dev/null +++ b/content/tutorial/01-simple-orders/meta.json @@ -0,0 +1,8 @@ +{ + "title": "Simple orders", + "scope": { + "prefix": "/src/lib/", + "name": "src" + }, + "focus": "/src/lib/run.ts" +} diff --git a/content/tutorial/01-orders/03-advanced-orders/tsconfig.json b/content/tutorial/01-simple-orders/tsconfig.json similarity index 100% rename from content/tutorial/01-orders/03-advanced-orders/tsconfig.json rename to content/tutorial/01-simple-orders/tsconfig.json diff --git a/content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/README.md b/content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/README.md new file mode 100644 index 0000000..b620c6e --- /dev/null +++ b/content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/README.md @@ -0,0 +1,131 @@ +--- +title: Eth-Flow +--- + +There are two types of wallets: + - EOA (externally owned account) wallets, which are controlled by a private key + - Smart contract wallets, which are controlled by a smart contract + +Since smart contract wallets are controlled by a smart contract, they can't sign transactions using `EIP-712`. +Anyway, CoW Protocol supports smart contract wallets by allowing them to create pre-signed orders. +The key of pre-signed orders is a transaction to Settlement contract that proves the ownership of an order. + +In this example we will create a pre-signed order using Safe, but you can use any smart contract wallet. + +## Required dependencies + +For pre-signed orders, we need to use: + - `OrderBookApi` to send an order to the CoW Protocol order-book + - `MetadataApi` to generate order meta data + - `Safe` to create and sign the transaction to the Settlement contract + - `SafeApiKit` to propose the transaction to Safe owners + +## Define the order parameters + +First of all, we should define the order parameters. +The description of each parameter can be found in the [Order structure docs.](https://TODO) + +``` +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+++ +} +``` + +> `signingScheme` is the only difference between a regular order and a pre-signed order + +## Order meta data + +For analytics purposes, we can add some metadata to the order. +The metadata is a JSON document that is stored in IPFS and referenced by the order. +The metadata is optional, but it's recommended to add it. +After order creation, the metadata will be displayed in [the Explorer](https://explorer.cow.fi/). + +``` +const appCode = '' +const environment = 'prod' + +// Slippage percent, it's 0 to 100 +const quote = { slippageBips: '50' } + +// "market" | "limit" | "liquidity" +const orderClass = { orderClass: 'limit' } + +// Generate the app-data document +const appDataDoc = await metadataApi.generateAppDataDoc({ + appCode, + environment, + metadata: { + quote, + orderClass + }, +}) + +const +++{ appDataHex, appDataContent }+++ = await metadataApi.appDataToCid(appDataDoc) +``` + +## Post the order to the order-book + +Having the order and the metadata, we can post the order to the order-book. +`orderId` is the ID of the order in the order-book, and it's a key for the Settlement contract transaction. + +``` +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 transaction to the Settlement contract + +In the previous step, we created an order in the order-book, but it's not valid yet. +To make it valid, we need to create a transaction to the Settlement contract that proves the ownership of the order. + +``` +// 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, +}) +``` + +## Sign and execute transaction + +After the transaction is proposed to the Safe, the Safe owners should sign and execute it. +After the transaction is executed, the order will be valid and can be filled. diff --git a/content/tutorial/01-orders/03-advanced-orders/03-pre-signed-order/app-a/src/lib/GPv2Settlement.json b/content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/app-a/src/lib/GPv2Settlement.json similarity index 100% rename from content/tutorial/01-orders/03-advanced-orders/03-pre-signed-order/app-a/src/lib/GPv2Settlement.json rename to content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/app-a/src/lib/GPv2Settlement.json diff --git a/content/tutorial/01-orders/03-advanced-orders/03-pre-signed-order/app-a/src/lib/const.ts b/content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/app-a/src/lib/const.ts similarity index 100% rename from content/tutorial/01-orders/03-advanced-orders/03-pre-signed-order/app-a/src/lib/const.ts rename to content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/app-a/src/lib/const.ts diff --git a/content/tutorial/01-orders/03-advanced-orders/03-pre-signed-order/app-a/src/lib/getSafeSdkAndKit.ts b/content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/app-a/src/lib/getSafeSdkAndKit.ts similarity index 100% rename from content/tutorial/01-orders/03-advanced-orders/03-pre-signed-order/app-a/src/lib/getSafeSdkAndKit.ts rename to content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/app-a/src/lib/getSafeSdkAndKit.ts diff --git a/content/tutorial/01-orders/03-advanced-orders/03-pre-signed-order/app-a/src/lib/run.ts b/content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/app-a/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/03-advanced-orders/03-pre-signed-order/app-a/src/lib/run.ts rename to content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/app-a/src/lib/run.ts diff --git a/content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/app-b/src/lib/run.ts b/content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/app-b/src/lib/run.ts new file mode 100644 index 0000000..224c7e2 --- /dev/null +++ b/content/tutorial/02-advanced-orders/01-eth-flow/01-create-eth-flow/app-b/src/lib/run.ts @@ -0,0 +1,108 @@ +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 { + const safeAddress = '' + const appCode = '' + 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 } +} diff --git a/content/tutorial/02-advanced-orders/01-eth-flow/02-view-eth-flow/README.md b/content/tutorial/02-advanced-orders/01-eth-flow/02-view-eth-flow/README.md new file mode 100644 index 0000000..f5536b7 --- /dev/null +++ b/content/tutorial/02-advanced-orders/01-eth-flow/02-view-eth-flow/README.md @@ -0,0 +1,5 @@ +--- +title: Viewing status +--- + +Something \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/01-eth-flow/03-cancel-eth-flow/README.md b/content/tutorial/02-advanced-orders/01-eth-flow/03-cancel-eth-flow/README.md new file mode 100644 index 0000000..29640d3 --- /dev/null +++ b/content/tutorial/02-advanced-orders/01-eth-flow/03-cancel-eth-flow/README.md @@ -0,0 +1,5 @@ +--- +title: Cancelling order +--- + +Something \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/01-eth-flow/meta.json b/content/tutorial/02-advanced-orders/01-eth-flow/meta.json new file mode 100644 index 0000000..5f1d3c2 --- /dev/null +++ b/content/tutorial/02-advanced-orders/01-eth-flow/meta.json @@ -0,0 +1,8 @@ +{ + "title": "Eth-Flow", + "scope": { + "prefix": "/src/lib/", + "name": "src" + }, + "focus": "/src/lib/run.ts" +} diff --git a/content/tutorial/01-orders/03-advanced-orders/03-pre-signed-order/README.md b/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/README.md similarity index 100% rename from content/tutorial/01-orders/03-advanced-orders/03-pre-signed-order/README.md rename to content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/README.md diff --git a/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/GPv2Settlement.json b/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/GPv2Settlement.json new file mode 100644 index 0000000..9a9e85e --- /dev/null +++ b/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/GPv2Settlement.json @@ -0,0 +1,20 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "orderUid", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "signed", + "type": "bool" + } + ], + "name": "setPreSignature", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/const.ts b/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/const.ts new file mode 100644 index 0000000..ac9e158 --- /dev/null +++ b/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/const.ts @@ -0,0 +1,12 @@ +import GPv2SettlementAbi from './GPv2Settlement.json' +import {SupportedChainId} from '@cowprotocol/cow-sdk' + +export const SETTLEMENT_CONTRACT_ADDRESS = '0x9008D19f58AAbD9eD0D60971565AA8510560ab41' + +export const SETTLEMENT_CONTRACT_ABI = GPv2SettlementAbi + +export const SAFE_TRANSACTION_SERVICE_URL: Record = { + [SupportedChainId.MAINNET]: 'https://safe-transaction-mainnet.safe.global', + [SupportedChainId.GNOSIS_CHAIN]: 'https://safe-transaction-gnosis-chain.safe.global', + [SupportedChainId.GOERLI]: 'https://safe-transaction-goerli.safe.global', +} diff --git a/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/getSafeSdkAndKit.ts b/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/getSafeSdkAndKit.ts new file mode 100644 index 0000000..fde4c44 --- /dev/null +++ b/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/getSafeSdkAndKit.ts @@ -0,0 +1,28 @@ +import Safe, { EthersAdapter } from '@safe-global/protocol-kit' +import { ethers } from 'ethers' +import SafeApiKit from '@safe-global/api-kit' +import type { Web3Provider } from '@ethersproject/providers' +import {SAFE_TRANSACTION_SERVICE_URL} from './const' + +interface SafeSdkAndKit { + safeApiKit: SafeApiKit, + safeSdk: Safe +} + +export async function getSafeSdkAndKit(chainId: number, provider: Web3Provider, safeAddress: string): Promise { + const ethAdapter = new EthersAdapter({ + ethers, + signerOrProvider: provider.getSigner(0), + }) + const safeApiKit = new SafeApiKit({ + txServiceUrl: SAFE_TRANSACTION_SERVICE_URL[chainId], + ethAdapter + }) + + return Safe.create({ethAdapter, safeAddress}).then(safeSdk => { + return { + safeApiKit, + safeSdk + } + }) +} diff --git a/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/run.ts b/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/run.ts new file mode 100644 index 0000000..44616eb --- /dev/null +++ b/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-a/src/lib/run.ts @@ -0,0 +1,41 @@ +import type { Web3Provider } from '@ethersproject/providers' +import { Contract } from '@ethersproject/contracts' + +import { OrderBookApi, UnsignedOrder, OrderKind, SigningScheme } from '@cowprotocol/cow-sdk' +import { getSafeSdkAndKit } from './getSafeSdkAndKit' + +import { SETTLEMENT_CONTRACT_ABI, SETTLEMENT_CONTRACT_ADDRESS } from './const' + +export async function run(provider: Web3Provider): Promise { + const safeAddress = '' + + // Get chainId and account from the current provider + const accounts = await provider.listAccounts() + const account = accounts[0] + const chainId = +(await provider.send('eth_chainId', [])) + + // Create the CoW Protocol OrderBookApi instance + const orderBookApi = new OrderBookApi({ chainId }) + + // 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) + + // Create 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, + } +} diff --git a/content/tutorial/01-orders/03-advanced-orders/03-pre-signed-order/app-b/src/lib/run.ts b/content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-b/src/lib/run.ts similarity index 100% rename from content/tutorial/01-orders/03-advanced-orders/03-pre-signed-order/app-b/src/lib/run.ts rename to content/tutorial/02-advanced-orders/02-pre-signed-orders/01-create-pre-signed-order/app-b/src/lib/run.ts diff --git a/content/tutorial/02-advanced-orders/02-pre-signed-orders/02-view-pre-signed-order/README.md b/content/tutorial/02-advanced-orders/02-pre-signed-orders/02-view-pre-signed-order/README.md new file mode 100644 index 0000000..f5536b7 --- /dev/null +++ b/content/tutorial/02-advanced-orders/02-pre-signed-orders/02-view-pre-signed-order/README.md @@ -0,0 +1,5 @@ +--- +title: Viewing status +--- + +Something \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/02-pre-signed-orders/03-cancel-pre-signed-order/README.md b/content/tutorial/02-advanced-orders/02-pre-signed-orders/03-cancel-pre-signed-order/README.md new file mode 100644 index 0000000..29640d3 --- /dev/null +++ b/content/tutorial/02-advanced-orders/02-pre-signed-orders/03-cancel-pre-signed-order/README.md @@ -0,0 +1,5 @@ +--- +title: Cancelling order +--- + +Something \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/02-pre-signed-orders/meta.json b/content/tutorial/02-advanced-orders/02-pre-signed-orders/meta.json new file mode 100644 index 0000000..d66bda9 --- /dev/null +++ b/content/tutorial/02-advanced-orders/02-pre-signed-orders/meta.json @@ -0,0 +1,8 @@ +{ + "title": "Pre-Signed", + "scope": { + "prefix": "/src/lib/", + "name": "src" + }, + "focus": "/src/lib/run.ts" +} diff --git a/content/tutorial/02-advanced-orders/03-hooks/01-app-data-hooks/README.md b/content/tutorial/02-advanced-orders/03-hooks/01-app-data-hooks/README.md new file mode 100644 index 0000000..2601036 --- /dev/null +++ b/content/tutorial/02-advanced-orders/03-hooks/01-app-data-hooks/README.md @@ -0,0 +1,5 @@ +--- +title: Creating app-data +--- + +Something \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/03-hooks/02-pre-hooks/README.md b/content/tutorial/02-advanced-orders/03-hooks/02-pre-hooks/README.md new file mode 100644 index 0000000..b695bb3 --- /dev/null +++ b/content/tutorial/02-advanced-orders/03-hooks/02-pre-hooks/README.md @@ -0,0 +1,5 @@ +--- +title: Pre-hook +--- + +Something about pre-hook \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/03-hooks/03-post-hooks/README.md b/content/tutorial/02-advanced-orders/03-hooks/03-post-hooks/README.md new file mode 100644 index 0000000..08e6df3 --- /dev/null +++ b/content/tutorial/02-advanced-orders/03-hooks/03-post-hooks/README.md @@ -0,0 +1,5 @@ +--- +title: Post-hook +--- + +Something about post-hook \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/03-hooks/04-permit-and-bridge-hooks/README.md b/content/tutorial/02-advanced-orders/03-hooks/04-permit-and-bridge-hooks/README.md new file mode 100644 index 0000000..e489bb4 --- /dev/null +++ b/content/tutorial/02-advanced-orders/03-hooks/04-permit-and-bridge-hooks/README.md @@ -0,0 +1,5 @@ +--- +title: Permit and Bridge +--- + +Permitting and bridging tokens \ No newline at end of file diff --git a/content/tutorial/01-orders/meta.json b/content/tutorial/02-advanced-orders/03-hooks/meta.json similarity index 81% rename from content/tutorial/01-orders/meta.json rename to content/tutorial/02-advanced-orders/03-hooks/meta.json index 6d7e99f..01b271b 100644 --- a/content/tutorial/01-orders/meta.json +++ b/content/tutorial/02-advanced-orders/03-hooks/meta.json @@ -1,5 +1,5 @@ { - "title": "Orders", + "title": "Hooks", "scope": { "prefix": "/src/lib/", "name": "src" diff --git a/content/tutorial/02-advanced-orders/04-milkman/01-create-milkman/README.md b/content/tutorial/02-advanced-orders/04-milkman/01-create-milkman/README.md new file mode 100644 index 0000000..330fd8c --- /dev/null +++ b/content/tutorial/02-advanced-orders/04-milkman/01-create-milkman/README.md @@ -0,0 +1,5 @@ +--- +title: Create order +--- + +Something \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/04-milkman/02-bot-milkman/README.md b/content/tutorial/02-advanced-orders/04-milkman/02-bot-milkman/README.md new file mode 100644 index 0000000..22ae55f --- /dev/null +++ b/content/tutorial/02-advanced-orders/04-milkman/02-bot-milkman/README.md @@ -0,0 +1,5 @@ +--- +title: In-browser bot +--- + +Something robotic \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/04-milkman/03-cancel-milkman/README.md b/content/tutorial/02-advanced-orders/04-milkman/03-cancel-milkman/README.md new file mode 100644 index 0000000..418b72e --- /dev/null +++ b/content/tutorial/02-advanced-orders/04-milkman/03-cancel-milkman/README.md @@ -0,0 +1,5 @@ +--- +title: Cancel order +--- + +Bail \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/04-milkman/04-triage-milkman/README.md b/content/tutorial/02-advanced-orders/04-milkman/04-triage-milkman/README.md new file mode 100644 index 0000000..7de51a3 --- /dev/null +++ b/content/tutorial/02-advanced-orders/04-milkman/04-triage-milkman/README.md @@ -0,0 +1,7 @@ +--- +title: Triage +--- + +Diagnosing problems + +https://etherscan.io/tx/0x03e18bc923d69b3706e6e7dfc84f1b958e7087b91806955739862c1cfa7b5cd1 \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/04-milkman/meta.json b/content/tutorial/02-advanced-orders/04-milkman/meta.json new file mode 100644 index 0000000..7fef0a9 --- /dev/null +++ b/content/tutorial/02-advanced-orders/04-milkman/meta.json @@ -0,0 +1,8 @@ +{ + "title": "Milkman", + "scope": { + "prefix": "/src/lib/", + "name": "src" + }, + "focus": "/src/lib/run.ts" +} diff --git a/content/tutorial/02-advanced-orders/05-programmatic/01-config-programmatic/README.md b/content/tutorial/02-advanced-orders/05-programmatic/01-config-programmatic/README.md new file mode 100644 index 0000000..4c499c2 --- /dev/null +++ b/content/tutorial/02-advanced-orders/05-programmatic/01-config-programmatic/README.md @@ -0,0 +1,5 @@ +--- +title: Configuration +--- + +Configure a safe wallet \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/05-programmatic/02-create-programmatic/README.md b/content/tutorial/02-advanced-orders/05-programmatic/02-create-programmatic/README.md new file mode 100644 index 0000000..6189f6c --- /dev/null +++ b/content/tutorial/02-advanced-orders/05-programmatic/02-create-programmatic/README.md @@ -0,0 +1,5 @@ +--- +title: Create an order +--- + +Something \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/05-programmatic/03-poll-programmatic/README.md b/content/tutorial/02-advanced-orders/05-programmatic/03-poll-programmatic/README.md new file mode 100644 index 0000000..8890c96 --- /dev/null +++ b/content/tutorial/02-advanced-orders/05-programmatic/03-poll-programmatic/README.md @@ -0,0 +1,5 @@ +--- +title: Polling for an order +--- + +Polllll \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/05-programmatic/04-remove-programmatic/README.md b/content/tutorial/02-advanced-orders/05-programmatic/04-remove-programmatic/README.md new file mode 100644 index 0000000..4cc9849 --- /dev/null +++ b/content/tutorial/02-advanced-orders/05-programmatic/04-remove-programmatic/README.md @@ -0,0 +1,5 @@ +--- +title: Remove order +--- + +Bye bye \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/05-programmatic/05-merkle/README.md b/content/tutorial/02-advanced-orders/05-programmatic/05-merkle/README.md new file mode 100644 index 0000000..0881f3a --- /dev/null +++ b/content/tutorial/02-advanced-orders/05-programmatic/05-merkle/README.md @@ -0,0 +1,5 @@ +--- +title: Merkle tree +--- + +It's trees all the way down. \ No newline at end of file diff --git a/content/tutorial/02-advanced-orders/05-programmatic/meta.json b/content/tutorial/02-advanced-orders/05-programmatic/meta.json new file mode 100644 index 0000000..ec3cf52 --- /dev/null +++ b/content/tutorial/02-advanced-orders/05-programmatic/meta.json @@ -0,0 +1,8 @@ +{ + "title": "Programmatic", + "scope": { + "prefix": "/src/lib/", + "name": "src" + }, + "focus": "/src/lib/run.ts" +} diff --git a/content/tutorial/01-orders/03-advanced-orders/meta.json b/content/tutorial/02-advanced-orders/meta.json similarity index 100% rename from content/tutorial/01-orders/03-advanced-orders/meta.json rename to content/tutorial/02-advanced-orders/meta.json diff --git a/content/tutorial/01-orders/tsconfig.json b/content/tutorial/02-advanced-orders/tsconfig.json similarity index 100% rename from content/tutorial/01-orders/tsconfig.json rename to content/tutorial/02-advanced-orders/tsconfig.json diff --git a/src/routes/+page.server.js b/src/routes/+page.server.js index 6b17235..36a8147 100644 --- a/src/routes/+page.server.js +++ b/src/routes/+page.server.js @@ -1,5 +1,5 @@ import { redirect } from '@sveltejs/kit'; export function load() { - throw redirect(307, '/tutorial/getting-started'); + throw redirect(307, '/tutorial/getting-started-order'); } diff --git a/src/routes/tutorial/+page.js b/src/routes/tutorial/+page.js index 6b17235..36a8147 100644 --- a/src/routes/tutorial/+page.js +++ b/src/routes/tutorial/+page.js @@ -1,5 +1,5 @@ import { redirect } from '@sveltejs/kit'; export function load() { - throw redirect(307, '/tutorial/getting-started'); + throw redirect(307, '/tutorial/getting-started-order'); } diff --git a/src/routes/tutorial/[slug]/+page.server.js b/src/routes/tutorial/[slug]/+page.server.js index f339456..2ee59bd 100644 --- a/src/routes/tutorial/[slug]/+page.server.js +++ b/src/routes/tutorial/[slug]/+page.server.js @@ -8,7 +8,7 @@ export function entries() { export async function load({ params }) { if (params.slug === 'local-transitions') { - throw redirect(307, '/tutorial/getting-started'); + throw redirect(307, '/tutorial/getting-started-order'); } const exercise = await get_exercise(params.slug); diff --git a/tests/env_file.spec.ts b/tests/env_file.spec.ts index 47a5def..6266694 100644 --- a/tests/env_file.spec.ts +++ b/tests/env_file.spec.ts @@ -9,7 +9,7 @@ test('.env file: no timeout error occurs when switching a tutorials without a .e }) => { await page.bringToFront(); - await page.goto('/tutorial/getting-started'); + await page.goto('/tutorial/getting-started-order'); const iframe_locator = page.frameLocator(iframe_selector); @@ -39,7 +39,7 @@ test('.env file: environment variables are available when switching a tutorial w }) => { await page.bringToFront(); - await page.goto('/tutorial/getting-started'); + await page.goto('/tutorial/getting-started-order'); const iframe_locator = page.frameLocator(iframe_selector);