Skip to content

Commit 477ce8b

Browse files
committed
Add Gnosis script to post an order with hooks in appData
Adds src/scripts/gnosis/postHookOrder.ts: posts a CoW order on Gnosis Chain carrying CoW hooks in the order's appData, and prints the full appData document + hash + order URL so we can inspect how the real backend/solvers convey and treat hooks. This is to validate the transport assumption behind an enforceable-hooks wrapper (cow-shed): that pre/post interactions and wrapper routing travel via appData. This SDK version exposes standard CoW hooks (metadata.hooks) but no wrapper/Atomic-Bundles field, so the script probes the hooks-in-appData path (the closest existing mechanism). Also adds WXDAI/COW Gnosis token constants and registers the script as the active JOBS entry.
1 parent e7a14ac commit 477ce8b

3 files changed

Lines changed: 104 additions & 1 deletion

File tree

src/const/gnosis.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export const GNO_ADDRESS = "0x9C58BAcC331c9aa871AFD802DB6379a98e80CEdb";
2+
export const WXDAI_ADDRESS = "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d";
3+
export const COW_ADDRESS = "0x177127622c4A00F3d409B75571e12cB3c8973d3c";

src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { run as swapSellWithSlippageTolerance } from "./scripts/sepolia/swapSell
2424
import { run as approveTokenMainnet } from "./scripts/mainnet/approveTokenMainnet";
2525
import { run as getQuoteAndPostOrderMainnet } from "./scripts/mainnet/getQuoteAndPostOrder";
2626
import { run as approveTokenGnosis } from "./scripts/gnosis/approveTokenGnosis";
27+
import { run as postHookOrderGnosis } from "./scripts/gnosis/postHookOrder";
2728
import { run as swapAndBridgeSwapsIo } from "./scripts/bridging/swapAndBridgeSwapsIO";
2829
import { run as approveTokenArbitrum } from "./scripts/arbitrum/approveTokenArbitrum";
2930
import { run as swapAndBridgeAccrossArbitrum } from "./scripts/bridging/swapAndBridgeAccrossArbitrum";
@@ -86,7 +87,10 @@ const JOBS: (() => Promise<unknown>)[] = [
8687
// getEthFlowId,
8788
// minimalAppData,
8889
// getIpfsForLegacyDoc,
89-
postTwapForEOA,
90+
// postTwapForEOA,
91+
92+
// Post a Gnosis order carrying CoW hooks in appData (enforceable-hooks assumption test)
93+
postHookOrderGnosis,
9094
];
9195

9296
async function main() {
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { gnosis, APP_CODE } from "../../const";
2+
const { WXDAI_ADDRESS, GNO_ADDRESS } = gnosis;
3+
import {
4+
SupportedChainId,
5+
OrderKind,
6+
TradeParameters,
7+
TradingSdk,
8+
} from "@cowprotocol/cow-sdk";
9+
import { MetadataApi } from "@cowprotocol/app-data";
10+
import { ethers } from "ethers";
11+
import { getWallet, jsonReplacer } from "../../utils";
12+
13+
/**
14+
* Post an order on Gnosis Chain with CoW Protocol hooks carried in the order's `appData`,
15+
* so we can inspect end-to-end how the real backend/solvers convey and treat hooks.
16+
*
17+
* Why this script exists
18+
* ----------------------
19+
* We're validating an assumption for an "enforceable hooks" wrapper (cow-shed): that the
20+
* pre/post interactions and any wrapper routing for an order travel in `appData`, and how the
21+
* backend serves that to solvers.
22+
*
23+
* What this SDK version supports
24+
* ------------------------------
25+
* `@cowprotocol/app-data` exposes standard **CoW hooks** (`metadata.hooks.pre` / `.post`, each a
26+
* `{ target, callData, gasLimit }`). It does NOT (in this version) expose a "wrapper" /
27+
* Atomic-Bundles field, so we cannot route an order through a settlement wrapper from here.
28+
* This script therefore probes the *hooks-in-appData* path — the closest existing mechanism —
29+
* and prints the full appData document + hash so we can inspect exactly what the backend stores
30+
* and serves. Extend `HOOKS` below as the wrapper appData schema becomes available.
31+
*
32+
* Env required: PRIVATE_KEY, RPC_URL_100.
33+
*/
34+
35+
// --- tweak me -------------------------------------------------------------
36+
const SELL_TOKEN = WXDAI_ADDRESS;
37+
const BUY_TOKEN = GNO_ADDRESS;
38+
const SELL_AMOUNT = ethers.utils.parseUnits("1", 18).toString(); // 1 WXDAI
39+
40+
// A benign no-op post-hook purely to exercise the hooks-in-appData path. Calling address(0)
41+
// with empty calldata is a harmless no-op a solver can execute. Replace with a real interaction
42+
// (e.g. a call routed through your cow-shed) once we test meaningful hooks.
43+
const HOOKS = {
44+
pre: [] as { target: string; callData: string; gasLimit: string }[],
45+
post: [
46+
{
47+
target: "0x0000000000000000000000000000000000000000",
48+
callData: "0x",
49+
gasLimit: "50000",
50+
},
51+
],
52+
};
53+
// -------------------------------------------------------------------------
54+
55+
export async function run() {
56+
const chainId = SupportedChainId.GNOSIS_CHAIN;
57+
const wallet = await getWallet(chainId);
58+
59+
const sdk = new TradingSdk({
60+
chainId,
61+
signer: wallet,
62+
appCode: APP_CODE,
63+
});
64+
65+
const parameters: TradeParameters = {
66+
kind: OrderKind.SELL,
67+
amount: SELL_AMOUNT,
68+
sellToken: SELL_TOKEN,
69+
sellTokenDecimals: 18,
70+
buyToken: BUY_TOKEN,
71+
buyTokenDecimals: 18,
72+
};
73+
74+
const metadataApi = new MetadataApi();
75+
const appData = await metadataApi.generateAppDataDoc({
76+
appCode: APP_CODE,
77+
metadata: {
78+
hooks: HOOKS,
79+
},
80+
});
81+
82+
// NOTE: `as any` bridges dual-package app-data type drift in this SDK RC (the standalone
83+
// `@cowprotocol/app-data` schema vs the copy bundled inside `@cowprotocol/cow-sdk`). The
84+
// runtime JSON is identical.
85+
// Inspect exactly what will be committed on-chain (hash) and served off-chain (full doc).
86+
const { appDataContent, appDataHex } = await metadataApi.getAppDataInfo(appData as any);
87+
console.log("📦 appData doc:", JSON.stringify(appData, jsonReplacer, 2));
88+
console.log("🧾 appData content (served to solvers):", appDataContent);
89+
console.log("#️⃣ appData hash (committed in the order):", appDataHex);
90+
91+
console.log(`\nPosting order on Gnosis (owner=${wallet.address})...`);
92+
const orderId = await sdk.postSwapOrder(parameters, { appData: appData as any });
93+
94+
console.log(
95+
`✅ Order created: https://explorer.cow.fi/gc/orders/${orderId}?tab=overview`
96+
);
97+
}

0 commit comments

Comments
 (0)