From 07038ff94e8ab3aba7e0505c1f39a7cd384a8824 Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 20 Jun 2026 17:53:13 +0000 Subject: [PATCH 1/3] Initial commit with task details Adding .gitkeep for PR creation (default mode). This file will be removed when the task is complete. Issue: https://github.com/xlabtg/teleton-plugins/issues/192 --- .gitkeep | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitkeep b/.gitkeep index 48587b8..cc169eb 100644 --- a/.gitkeep +++ b/.gitkeep @@ -3,4 +3,5 @@ # Updated: 2026-04-05T19:20:26.278Z # Updated: 2026-04-09T18:02:32.277Z # Updated: 2026-06-14T10:40:42.180Z -# Updated: 2026-06-14T10:41:34.176Z \ No newline at end of file +# Updated: 2026-06-14T10:41:34.176Z +# Updated: 2026-06-20T17:53:13.147Z \ No newline at end of file From 50beb0dba0012fbabec1980993e0147cd9b85303 Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 20 Jun 2026 18:03:41 +0000 Subject: [PATCH 2/3] =?UTF-8?q?docs(polymarket):=20=D0=B4=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D1=82=D1=8C=20=D0=B8=D0=BD=D1=81=D1=82=D1=80?= =?UTF-8?q?=D1=83=D0=BA=D1=86=D0=B8=D1=8E=20=D0=BF=D0=BE=20=D1=81=D0=B5?= =?UTF-8?q?=D0=BA=D1=80=D0=B5=D1=82=D0=B0=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/polymarket/README.md | 2 + plugins/polymarket/SECRETS.md | 168 ++++++++++++++++++++++++++ plugins/polymarket/tests/docs.test.js | 25 ++++ 3 files changed, 195 insertions(+) create mode 100644 plugins/polymarket/SECRETS.md create mode 100644 plugins/polymarket/tests/docs.test.js diff --git a/plugins/polymarket/README.md b/plugins/polymarket/README.md index 5c9a419..7c3a65e 100644 --- a/plugins/polymarket/README.md +++ b/plugins/polymarket/README.md @@ -44,6 +44,8 @@ Configured via Teleton secrets (never logged, never returned): | `POLY_API_PASSPHRASE` | ✅ | Polymarket CLOB API passphrase | | `CHANGENOW_API_KEY` | ✅ | ChangeNOW API key for the bridge | +Detailed setup: [SECRETS.md](SECRETS.md). + > Use a **fresh, dedicated** EVM key holding only your trading USDC. The withdraw > flow broadcasts an on-chain ERC‑20 transfer, so the EVM wallet also needs a > little **MATIC** for gas. diff --git a/plugins/polymarket/SECRETS.md b/plugins/polymarket/SECRETS.md new file mode 100644 index 0000000..1d2ab81 --- /dev/null +++ b/plugins/polymarket/SECRETS.md @@ -0,0 +1,168 @@ +# Polymarket Secrets Setup + +This plugin needs five Teleton secrets: + +| Secret | Source | Used for | +| --- | --- | --- | +| `EVM_PRIVATE_KEY` | A fresh Polygon-compatible EVM wallet | EIP-712 order signing and USDC transfers on Polygon | +| `POLY_API_KEY` | Polymarket CLOB L2 credentials | Authenticated CLOB requests | +| `POLY_API_SECRET` | Polymarket CLOB L2 credentials | HMAC signing for authenticated CLOB requests | +| `POLY_API_PASSPHRASE` | Polymarket CLOB L2 credentials | Authenticated CLOB requests | +| `CHANGENOW_API_KEY` | ChangeNOW Partner account | TON <-> USDC bridge quotes and swaps | + +Keep these values out of git, logs, screenshots, and ordinary chat history. Use a +dedicated wallet that holds only the funds you are prepared to trade with this +plugin. + +## Compatibility Note + +The current plugin signs Polymarket orders as a direct EOA wallet +(`signatureType = 0`). Polymarket also documents proxy, Safe, and deposit wallet +flows with a separate funder address. Do not use credentials created for those +flows with this plugin unless the plugin is extended to support `signatureType` +and `funderAddress`. + +Use the same EOA private key for `EVM_PRIVATE_KEY` and for deriving the +`POLY_*` credentials below. The EOA address is the address that will hold Polygon +USDC and the native Polygon gas token, POL/MATIC. + +## 1. Create The EVM Wallet + +You can generate a fresh EVM key with the helper already included in this +plugin: + +```bash +node --input-type=module -e 'import { generateKeypair } from "./plugins/polymarket/lib/evm-wallet.js"; console.log(JSON.stringify(generateKeypair(), null, 2));' +``` + +Example shape: + +```json +{ + "address": "0x...", + "privateKey": "0x..." +} +``` + +Save the `privateKey` value as `EVM_PRIVATE_KEY`. Save the `address` value for +funding and checks. Never reuse a personal wallet or the Teleton TON wallet +mnemonic here; this must be a Polygon/EVM key. + +Fund the EVM address with: + +- Polygon USDC for Polymarket orders. +- A small amount of the native Polygon gas token, shown as POL or MATIC by + different wallets, for withdrawals and ERC-20 transfers. + +## 2. Derive The Polymarket CLOB Credentials + +Polymarket CLOB authentication has two levels: + +- L1: the EVM private key signs an ownership message. +- L2: the resulting API key, secret, and passphrase sign authenticated CLOB + requests. + +Use the official Polymarket CLOB SDK in a temporary directory. This keeps the +plugin dependency-free while still using Polymarket's signing flow. + +```bash +mkdir -p /tmp/polymarket-clob-auth +cd /tmp/polymarket-clob-auth +npm init -y +npm install @polymarket/clob-client-v2 viem +PRIVATE_KEY=0xYOUR_DEDICATED_EVM_PRIVATE_KEY node --input-type=module <<'EOF' +import { ClobClient } from "@polymarket/clob-client-v2"; +import { createWalletClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; + +const host = "https://clob.polymarket.com"; +const chain = 137; +const account = privateKeyToAccount(process.env.PRIVATE_KEY); +const signer = createWalletClient({ + account, + transport: http("https://polygon-rpc.com"), +}); + +const client = new ClobClient({ host, chain, signer }); +const credentials = await client.createOrDeriveApiKey(); +console.log(JSON.stringify(credentials, null, 2)); +EOF +``` + +Map the output into Teleton secrets: + +| SDK output field | Teleton secret | +| --- | --- | +| `key` or `apiKey` | `POLY_API_KEY` | +| `secret` | `POLY_API_SECRET` | +| `passphrase` | `POLY_API_PASSPHRASE` | + +If Polymarket returns `L2 AUTH NOT AVAILABLE`, `INVALID_SIGNATURE`, or +`Invalid Funder Address`, re-check that the private key is the same EOA key you +will store as `EVM_PRIVATE_KEY` and that you are not deriving credentials for a +proxy, Safe, or deposit wallet flow. + +## 3. Get The ChangeNOW API Key + +Create or open a ChangeNOW Partner account: + +1. Go to or . +2. Register or sign in. +3. Open `Dashboard > Profile settings > Account details`. +4. Copy the API key and store it as `CHANGENOW_API_KEY`. + +ChangeNOW normally creates one API key per partner account. If the key is +rotated in ChangeNOW, update the Teleton secret before using deposit or withdraw +tools again. + +## 4. Store The Secrets In Teleton + +Use your Teleton deployment's secrets UI, or set them from an admin chat/console +with: + +```text +/secret set polymarket EVM_PRIVATE_KEY "0x..." +/secret set polymarket POLY_API_KEY "..." +/secret set polymarket POLY_API_SECRET "..." +/secret set polymarket POLY_API_PASSPHRASE "..." +/secret set polymarket CHANGENOW_API_KEY "..." +``` + +For container and CI-style deployments, Teleton also resolves plugin secrets +from environment variables derived from the plugin id and key: + +```bash +POLYMARKET_EVM_PRIVATE_KEY=0x... +POLYMARKET_POLY_API_KEY=... +POLYMARKET_POLY_API_SECRET=... +POLYMARKET_POLY_API_PASSPHRASE=... +POLYMARKET_CHANGENOW_API_KEY=... +``` + +Restart or reload the Teleton agent after changing secrets if your deployment +does not hot-reload plugin secrets. + +## 5. Verify The Setup + +Start with read-only checks: + +1. Run `polymarket_list_markets` to verify public Polymarket access. +2. Run `polymarket_get_balance` to verify that `EVM_PRIVATE_KEY` is readable and + the EVM address is derived correctly. +3. Run `polymarket_deposit` without `confirm=true` to verify the ChangeNOW key + and receive a preview only. + +Only after these checks pass, place a very small order or run a small bridge +operation. Keep `max_order_usdc`, `max_swap_ton`, and +`require_confirmation_above_usdc` conservative until the full flow is proven. + +## External References + +- Polymarket authentication: + +- Polymarket trading quickstart: + +- ChangeNOW API: + +- ChangeNOW Partner account: + diff --git a/plugins/polymarket/tests/docs.test.js b/plugins/polymarket/tests/docs.test.js new file mode 100644 index 0000000..9f60c0d --- /dev/null +++ b/plugins/polymarket/tests/docs.test.js @@ -0,0 +1,25 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { readFile } from "node:fs/promises"; + +async function readPluginFile(name) { + return readFile(new URL(`../${name}`, import.meta.url), "utf8"); +} + +test("secret setup guide documents every required secret", async () => { + const manifest = JSON.parse(await readPluginFile("manifest.json")); + const readme = await readPluginFile("README.md"); + + assert.match(readme, /\[.*SECRETS\.md.*\]\(.*SECRETS\.md.*\)/); + + const guide = await readPluginFile("SECRETS.md"); + for (const [name, spec] of Object.entries(manifest.secrets)) { + assert.equal(spec.required, true, `${name} should stay documented as required`); + assert.match(guide, new RegExp(`\\\`${name}\\\``), `${name} is missing from SECRETS.md`); + assert.match(guide, new RegExp(`/secret set polymarket ${name}\\b`), `${name} is missing a Teleton command`); + } + + assert.match(guide, /POLYMARKET_EVM_PRIVATE_KEY/); + assert.match(guide, /createOrDeriveApiKey/); + assert.match(guide, /ChangeNOW/); +}); From 79a88e9681607c1d8eb914822dab9a79377563d8 Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 20 Jun 2026 18:07:06 +0000 Subject: [PATCH 3/3] =?UTF-8?q?chore:=20=D1=83=D0=B1=D1=80=D0=B0=D1=82?= =?UTF-8?q?=D1=8C=20=D0=B2=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD=D0=BE=D0=B5?= =?UTF-8?q?=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20git?= =?UTF-8?q?keep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitkeep | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitkeep b/.gitkeep index cc169eb..48587b8 100644 --- a/.gitkeep +++ b/.gitkeep @@ -3,5 +3,4 @@ # Updated: 2026-04-05T19:20:26.278Z # Updated: 2026-04-09T18:02:32.277Z # Updated: 2026-06-14T10:40:42.180Z -# Updated: 2026-06-14T10:41:34.176Z -# Updated: 2026-06-20T17:53:13.147Z \ No newline at end of file +# Updated: 2026-06-14T10:41:34.176Z \ No newline at end of file