@vercora-protocol/sdk 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +34 -34
- package/agents/skill.md +15 -13
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ All notable changes to `@vercora-protocol/sdk` are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
7
|
|
|
8
|
+
## [0.5.0](https://github.com/vercora/vercora-anchor/compare/v0.4.2...v0.5.0) (2026-05-01)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **all:** update brand position and landing page ([4e6f1a9](https://github.com/vercora/vercora-anchor/commit/4e6f1a9a351f5de532d2414190969575b5345850))
|
|
14
|
+
|
|
8
15
|
### [0.4.2](https://github.com/vercora/vercora-anchor/compare/v0.4.1...v0.4.2) (2026-04-24)
|
|
9
16
|
|
|
10
17
|
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @vercora-protocol/sdk
|
|
2
2
|
|
|
3
|
-
TypeScript SDK for
|
|
3
|
+
TypeScript SDK for **[Vercora Protocol](https://vercora.xyz)** on Solana (Anchor). **Vercora** is **token utility infrastructure** for LST and utility-token programs; **this package** documents the **outcome markets** program today (`PredictionMarketClient`, bundled IDL). A second product lane (issuer upside and diversification into broader assets) is on the **roadmap** and is **not** exposed in this SDK yet.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ npm install @vercora-protocol/sdk
|
|
|
10
10
|
yarn add @vercora-protocol/sdk
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
**Peer dependencies** (install alongside
|
|
13
|
+
**Peer dependencies** (install alongside, keep versions aligned; see [IDL, account metas, and peer deps](#idl-account-metas-and-peer-deps-browser--raw-anchor) for SendTransactionError notes):
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
npm install @coral-xyz/anchor @solana/web3.js @solana/spl-token bn.js
|
|
@@ -30,7 +30,7 @@ const connection = new Connection(clusterApiUrl("devnet"));
|
|
|
30
30
|
const provider = new anchor.AnchorProvider(connection, wallet, {});
|
|
31
31
|
anchor.setProvider(provider);
|
|
32
32
|
|
|
33
|
-
// Bundled IDL
|
|
33
|
+
// Bundled IDL, program id is embedded in `IDL.address` (`PROGRAM_ID` matches it)
|
|
34
34
|
const program = new anchor.Program<Vercora>(IDL, provider);
|
|
35
35
|
const client = new PredictionMarketClient(program);
|
|
36
36
|
```
|
|
@@ -63,19 +63,19 @@ For **`claim_resolver_stake`** and **`resolve_refute`**, the program may transfe
|
|
|
63
63
|
|
|
64
64
|
### Served IDL vs package IDL (drift and disputerCollateral not provided)
|
|
65
65
|
|
|
66
|
-
If the app loads IDL from **`fetchIdl()`**, a static **`public/idl/vercora.json`**, or a CDN URL, it can **drift** from `node_modules/@vercora-protocol/sdk/dist/idl/vercora.json`. Anchor then builds **wrong or incomplete account lists** while `PredictionMarketClient` assumes the bundled layout
|
|
66
|
+
If the app loads IDL from **`fetchIdl()`**, a static **`public/idl/vercora.json`**, or a CDN URL, it can **drift** from `node_modules/@vercora-protocol/sdk/dist/idl/vercora.json`. Anchor then builds **wrong or incomplete account lists** while `PredictionMarketClient` assumes the bundled layout, e.g. **`Account 'disputerCollateral' not provided`** when metas omit accounts present in the current IDL.
|
|
67
67
|
|
|
68
68
|
**Recommendation:** Prefer **`import { IDL } from '@vercora-protocol/sdk'`** (or copy **`dist/idl/vercora.json`** from the exact npm version) so the Program client and high-level client agree. If you must hot-reload IDL from HTTP, **version and cache-bust** the URL to match the deployed program + SDK release.
|
|
69
69
|
|
|
70
70
|
### Disputer collateral on resolve_refute
|
|
71
71
|
|
|
72
|
-
**`disputer_collateral`** is the **refuter’s collateral SPL ATA** for the market mint
|
|
72
|
+
**`disputer_collateral`** is the **refuter’s collateral SPL ATA** for the market mint, the same role as **`refuter_collateral`** on **`open_refute`**. It is **always** in the **`resolve_refute`** account list: on **dismiss** the handler does not transfer the refute bond into it, but the account must still be present and valid (mint + **owner = `ResolutionState.disputer`**). On **accept**, the bond is refunded into this ATA.
|
|
73
73
|
|
|
74
74
|
It is **not** the market trading vault, pari pool vault, or treasury ATA.
|
|
75
75
|
|
|
76
76
|
### Who may sign resolve_refute (vs market resolvers)
|
|
77
77
|
|
|
78
|
-
**Signers:** **`GlobalConfig`** **primary** or **secondary** authority, **or** **`PlatformRegistry.profile_authority`** (platform operator). These are **config / registry** keys
|
|
78
|
+
**Signers:** **`GlobalConfig`** **primary** or **secondary** authority, **or** **`PlatformRegistry.profile_authority`** (platform operator). These are **config / registry** keys, **not** the per-market **`voteResolution`** resolver wallets.
|
|
79
79
|
|
|
80
80
|
**`GlobalConfig.dispute_resolution_authority`** (if still present in older docs) is **legacy / unused** for **`resolve_refute`** authorization; do not assume market resolver PDAs can sign it.
|
|
81
81
|
|
|
@@ -120,11 +120,11 @@ Public properties: **`program`**, **`connection`**, **`globalConfig`** (PDA).
|
|
|
120
120
|
| `createMarketFull(creator, collateralMint, creatorFeeAccount, resolverPubkeys, params)` | Runs create → outcomes → resolvers (+ mints **or** pari state in one flow). |
|
|
121
121
|
| `updateParimutuelState(marketPda, params)` | Creator updates penalty split, **`isEarlyWithdrawAllowed`**, **`maxWalletOutcomeInvestment`**, and **`isWalletOutcomeStakeExact`** (open pari pool). |
|
|
122
122
|
|
|
123
|
-
**`CreateMarketParams`:** requires **`platformId`** (**`> 0`**, BN) with a registered platform + **`upsertPlatformProfile`** (global config authority; resolver stake, challenge window, and refute bond are set on the profile
|
|
123
|
+
**`CreateMarketParams`:** requires **`platformId`** (**`> 0`**, BN) with a registered platform + **`upsertPlatformProfile`** (global config authority; resolver stake, challenge window, and refute bond are set on the profile, not per market). **`CreateMarketParams` (pari-mutuel):** optional **`isEarlyWithdrawAllowed`** (default **`true`**). Optional **`maxWalletOutcomeInvestment`** (`BN`, **`0`** = unlimited per-wallet per-outcome net stake cap in collateral base units). Optional **`isWalletOutcomeStakeExact`**: when **`true`** (parimutuel only), each stake must bring the wallet’s net on that outcome to **exactly** `maxWalletOutcomeInvestment`; requires **`maxWalletOutcomeInvestment > 0`**. Setting exact mode on a complete-set market fails with **`InvalidWalletOutcomeStakeExactConfig`**. Ignored for complete-set markets otherwise.
|
|
124
124
|
|
|
125
|
-
**`UpdateParimutuelStateParams`:** every call writes **all** fields
|
|
125
|
+
**`UpdateParimutuelStateParams`:** every call writes **all** fields, pass **current** values from **`fetchMarket`** / **`fetchParimutuelState`** for anything you are not changing. Includes **`earlyWithdrawPenaltyBps`**, **`penaltyKeptInPoolBps`**, **`isEarlyWithdrawAllowed`**, **`maxWalletOutcomeInvestment`**, **`isWalletOutcomeStakeExact`**. If **`isWalletOutcomeStakeExact`** is **`true`**, **`maxWalletOutcomeInvestment`** must be **> 0** (same rule as create). Use this to tighten or relax per-wallet caps and to toggle exact vs ceiling mode **after** launch (market must still be open and not resolved/voided).
|
|
126
126
|
|
|
127
|
-
When **`isEarlyWithdrawAllowed`** is **`false`**, early **`parimutuelWithdraw`** fails with **`EarlyWithdrawNotAllowed`** until close or resolution **(voided markets are exempt
|
|
127
|
+
When **`isEarlyWithdrawAllowed`** is **`false`**, early **`parimutuelWithdraw`** fails with **`EarlyWithdrawNotAllowed`** until close or resolution **(voided markets are exempt, full net-stake refunds, no penalty fees).** Read **`fetchMarket(marketPda)`** for **`isEarlyWithdrawAllowed`**, **`maxWalletOutcomeInvestment`**, **`isWalletOutcomeStakeExact`**.
|
|
128
128
|
|
|
129
129
|
### Complete-set trading
|
|
130
130
|
|
|
@@ -148,18 +148,18 @@ When **`isEarlyWithdrawAllowed`** is **`false`**, early **`parimutuelWithdraw`**
|
|
|
148
148
|
| ----------------------------------------- | --------------------------------------------- |
|
|
149
149
|
| `voteResolution(marketPda, params)` | Resolver vote; may escrow **resolver stake** to the market’s resolver stake vault (see platform policy). |
|
|
150
150
|
| `revokeResolutionVote(marketPda, params)` | Clear vote before changing (blocked once a proposal exists). |
|
|
151
|
-
| `finalizeResolution(marketPda, params)` | When M-of-N agree on one outcome, **proposes** that outcome
|
|
151
|
+
| `finalizeResolution(marketPda, params)` | When M-of-N agree on one outcome, **proposes** that outcome, sets `ResolutionState.proposed_outcome` + `proposal_ts`; does **not** set `Market.winning_outcome_index` yet. |
|
|
152
152
|
| `confirmResolution(marketPda, params)` | After the **challenge window** elapses with **no open dispute**, anyone can call this to set **`Market.winning_outcome_index`** (final approval / settlement). |
|
|
153
153
|
| `openRefute(marketPda, params)` | During the challenge window: post a **refute bond** and name an alternative winning outcome (dispute). |
|
|
154
154
|
| `resolveRefute(marketPda, params)` | `params.accept === false`: slash refute bond to treasury. `accept === true`: refund bond to refuter and set **`winning_outcome_index`** to disputed outcome (no **`confirmResolution`**). **Signer (not market resolvers):** global **primary or secondary** authority, or platform **`profileAuthority`**. Optional **`params.disputerCollateral`** defaults to the refuter’s ATA derived from **`ResolutionState.disputer`**. |
|
|
155
155
|
| `claimResolverStake(marketPda, params)` | After resolution: matching vote → stake returned to resolver; otherwise stake **slashed** to platform treasury. |
|
|
156
156
|
| `fetchResolutionState(marketPda)` | Read proposal, dispute, refute bond locked (`ResolutionState`). Challenge length and resolver stake size come from **`fetchPlatformProfile`**. |
|
|
157
157
|
| `closeMarketEarly(marketPda, params)` | Creator / config authority before `close_at`. |
|
|
158
|
-
| `voidMarket(marketPda, params)` | Void market. **Creator** cannot void while pari **outcome pools** (active stakes) or complete-set outstanding is non-zero
|
|
158
|
+
| `voidMarket(marketPda, params)` | Void market. **Creator** cannot void while pari **outcome pools** (active stakes) or complete-set outstanding is non-zero, use a **global config** authority to cancel live markets. **Cannot void while a refute dispute is open.** Parimutuel: then **`parimutuelWithdraw`** for full net refunds. |
|
|
159
159
|
| `claimVoidedParimutuelSurplus(marketPda, params)` | **Global config authority only.** After void, if pari **outcome pools** are zero but **`total_pool`** still holds early-exit **pool-keep** (no stakers left), sweeps that amount from the vault to the platform treasury. |
|
|
160
160
|
| `abandonMarket(marketPda, params)` | Creator abandons empty market (reclaim rent). |
|
|
161
161
|
|
|
162
|
-
**`resolveRefute
|
|
162
|
+
**`resolveRefute`, account meta `disputerCollateral` (common pitfall):** Anchor’s JS client expects **camelCase** keys in `.accounts()` / `.accountsStrict()`, matching the camelCase IDL. The JSON IDL field is `disputer_collateral`; if you pass **`disputer_collateral`** in the accounts object, Anchor ignores it and you get **`Account 'disputerCollateral' not provided`**. Use **`disputerCollateral`**. The account is **always required** for the instruction (see **Disputer collateral on resolve_refute** under [IDL, account metas, and peer deps](#idl-account-metas-and-peer-deps-browser--raw-anchor), dismiss does not fund it, but it must be present). For raw `program.methods`, supply every remaining account explicitly; **`as never`** on the accounts object is only to satisfy stale generated TypeScript, the chain still needs the meta. **IDL drift** (served JSON vs npm bundle) also produces “not provided”; prefer **`import { IDL } from '@vercora-protocol/sdk'`** or the same **`dist/idl/vercora.json`** as your installed package version.
|
|
163
163
|
|
|
164
164
|
#### `resolveRefute` examples
|
|
165
165
|
|
|
@@ -214,7 +214,7 @@ await program.methods
|
|
|
214
214
|
resolutionState: resolutionStatePk,
|
|
215
215
|
resolverStakeVault: deriveResolverStakeVault(program.programId, marketPda),
|
|
216
216
|
collateralMint,
|
|
217
|
-
disputerCollateral, // required
|
|
217
|
+
disputerCollateral, // required, camelCase key (`disputer_collateral` in JSON IDL is ignored)
|
|
218
218
|
globalConfig: deriveGlobalConfig(program.programId),
|
|
219
219
|
platformRegistry: derivePlatformRegistry(program.programId, marketAccount.platformId),
|
|
220
220
|
platformTreasuryWallet,
|
|
@@ -281,7 +281,7 @@ import { PublicKey } from "@solana/web3.js";
|
|
|
281
281
|
import BN from "bn.js";
|
|
282
282
|
|
|
283
283
|
await client.initializeConfig({
|
|
284
|
-
// System program / “none” placeholder
|
|
284
|
+
// System program / “none” placeholder, use a real secondary authority pubkey in production
|
|
285
285
|
secondaryAuthority: new PublicKey("11111111111111111111111111111111"),
|
|
286
286
|
depositPlatformFeeBps: 100,
|
|
287
287
|
platformTreasuryWallet: treasuryPubkey,
|
|
@@ -324,7 +324,7 @@ const { marketPda } = await client.createMarket(
|
|
|
324
324
|
maxOutcomeInvestment: new BN(0),
|
|
325
325
|
title: "Will it rain tomorrow?",
|
|
326
326
|
marketType: "completeSet",
|
|
327
|
-
platformId: new BN(1), // must be > 0
|
|
327
|
+
platformId: new BN(1), // must be > 0, register_platform + upsert_platform_profile first
|
|
328
328
|
categoryId: new BN(0),
|
|
329
329
|
},
|
|
330
330
|
);
|
|
@@ -390,7 +390,7 @@ const marketPda = await client.createMarketFull(
|
|
|
390
390
|
outcomeLabels: ["A", "B"],
|
|
391
391
|
platformId: new BN(1),
|
|
392
392
|
categoryId: new BN(0),
|
|
393
|
-
// Optional
|
|
393
|
+
// Optional, default true. Set false to lock stakes until close/resolution (no early parimutuelWithdraw).
|
|
394
394
|
isEarlyWithdrawAllowed: true,
|
|
395
395
|
parimutuelInit: {
|
|
396
396
|
earlyWithdrawPenaltyBps: 500,
|
|
@@ -451,7 +451,7 @@ await client.parimutuelWithdraw(marketPda, {
|
|
|
451
451
|
outcomeIndex: 0,
|
|
452
452
|
amount: new BN(500_000),
|
|
453
453
|
});
|
|
454
|
-
// If Market.isEarlyWithdrawAllowed is false (from create or updateParimutuelState), parimutuelWithdraw throws EarlyWithdrawNotAllowed
|
|
454
|
+
// If Market.isEarlyWithdrawAllowed is false (from create or updateParimutuelState), parimutuelWithdraw throws EarlyWithdrawNotAllowed, unless the market is voided (then full net stake back, no fees).
|
|
455
455
|
|
|
456
456
|
// After voidMarket on a pari pool, recover stakes (repeat per outcome / until active stake is 0):
|
|
457
457
|
// await client.voidMarket(marketPda, { marketId });
|
|
@@ -533,7 +533,7 @@ const all = await client.fetchAllMarkets();
|
|
|
533
533
|
// By platform (memcmp)
|
|
534
534
|
const byPlatform = await client.fetchAllMarkets(new BN(1));
|
|
535
535
|
|
|
536
|
-
// Markets created by a wallet
|
|
536
|
+
// Markets created by a wallet, full rows with labels + filters
|
|
537
537
|
const mine = await client.getUsersMarkets(creatorPubkey, {
|
|
538
538
|
platformId: new BN(1), // optional RPC filter
|
|
539
539
|
categoryId: 2, // optional; applied after decode
|
|
@@ -558,25 +558,25 @@ const profile = await client.fetchUserProfile(wallet.publicKey);
|
|
|
558
558
|
|
|
559
559
|
## Resolution approval flow (propose → challenge → confirm or refute-accept)
|
|
560
560
|
|
|
561
|
-
Settlement is **two-phase**: first a **proposal** is recorded on `ResolutionState`, then
|
|
561
|
+
Settlement is **two-phase**: first a **proposal** is recorded on `ResolutionState`, then, after an optional **challenge window**, the market is **approved** into a final winner on the `Market` account.
|
|
562
562
|
|
|
563
|
-
1. **Platform prerequisite
|
|
563
|
+
1. **Platform prerequisite**, `create_market` requires **`platform_id > 0`**: a registered **`PlatformRegistry`**, an initialized **`PlatformProfile`** (single **`resolver_stake`**, **`challenge_window_secs`**, **`refute_bond`** for that platform), and PDAs for **`resolution_state`** and **`resolver_stake_vault`**.
|
|
564
564
|
|
|
565
|
-
2. **Votes
|
|
565
|
+
2. **Votes**, Each assigned resolver calls **`voteResolution`** with their outcome. Votes update per-outcome tallies; resolver **stake** (from **`PlatformProfile.resolver_stake`**) transfers into the market’s **resolver stake vault**.
|
|
566
566
|
|
|
567
|
-
3. **Propose (`finalizeResolution`)
|
|
567
|
+
3. **Propose (`finalizeResolution`)**, When at least **`resolution_threshold`** resolvers agree on the **same** outcome, anyone may call **`finalizeResolution`**. On-chain this **does not** immediately set `Market.winning_outcome_index`. It sets **`ResolutionState.proposed_outcome`**, **`proposal_ts`**, and starts the **challenge window** (duration from **`PlatformProfile.challenge_window_secs`**).
|
|
568
568
|
|
|
569
|
-
4. **Challenge window
|
|
569
|
+
4. **Challenge window**, Until **`proposal_ts + challenge_window_secs`** elapses, a participant may **`openRefute`** with **exactly** **`platform_profile.refute_bond`**: lock that collateral and assert a **different** winning outcome. An authorized party (global **primary or secondary** authority, or platform **`profileAuthority`**) may **`resolveRefute`**: **`accept: false`** dismisses (bond → treasury), **`accept: true`** accepts (bond refunded, **`winning_outcome_index`** set immediately). While a dispute is active, **`confirmResolution`** is rejected. **`voidMarket`** is rejected while a dispute is open.
|
|
570
570
|
|
|
571
|
-
5. **Confirm (final approval)
|
|
571
|
+
5. **Confirm (final approval)**, After **`proposal_ts + challenge_window`**, if there is **no** blocking dispute and the market was not already finalized by **`resolveRefute(accept: true)`**, anyone calls **`confirmResolution`**. This writes **`Market.winning_outcome_index`**, the outcome is now final for **`redeemWinning`** / **`parimutuelClaim`**.
|
|
572
572
|
|
|
573
|
-
6. **Resolver stake
|
|
573
|
+
6. **Resolver stake**, After settlement, resolvers use **`claimResolverStake`**: stake returns to the resolver if their vote matched the final winner; otherwise it is transferred to the platform treasury.
|
|
574
574
|
|
|
575
575
|
**Reads**
|
|
576
576
|
|
|
577
|
-
- **`fetchResolutionState(marketPda)
|
|
578
|
-
- **`fetchPlatformProfile(platformId)
|
|
579
|
-
- **`fetchMarket(marketPda)
|
|
577
|
+
- **`fetchResolutionState(marketPda)`**, `proposed_outcome`, `proposal_ts`, `dispute_active`, `refute_bond_amount`, etc.
|
|
578
|
+
- **`fetchPlatformProfile(platformId)`**, `challenge_window_secs`, `resolver_stake`, `refute_bond` (challenge length and stake are not stored on `ResolutionState`).
|
|
579
|
+
- **`fetchMarket(marketPda)`**, `winningOutcomeIndex` is **`null`** until **`confirmResolution`** or **`resolveRefute({ accept: true })`** succeeds.
|
|
580
580
|
|
|
581
581
|
**UI / agent logic**
|
|
582
582
|
|
|
@@ -587,10 +587,10 @@ Settlement is **two-phase**: first a **proposal** is recorded on `ResolutionStat
|
|
|
587
587
|
|
|
588
588
|
On-chain, **`platform_id`** is **`u32`** and **`category_id`** is **`u8`** in `CreateMarketArgs` (not pubkeys).
|
|
589
589
|
|
|
590
|
-
1. **`register_platform
|
|
591
|
-
2. **`upsert_platform_profile
|
|
592
|
-
3. **`create_market_category
|
|
593
|
-
4. **`create_market
|
|
590
|
+
1. **`register_platform`**, assigns the next id from `GlobalConfig.next_platform_id` (starts at **1**); PDA `["platform", platform_id le u32]`.
|
|
591
|
+
2. **`upsert_platform_profile`**, metadata + **resolution policy** (`resolver_stake`, `challenge_window_secs`, `refute_bond`); signed by **global config** primary or secondary authority.
|
|
592
|
+
3. **`create_market_category`**, `category_id` must equal `PlatformRegistry.next_category_id`; PDA `["market-category", platform_id, category_id]`.
|
|
593
|
+
4. **`create_market`**, requires **`platform_id > 0`**, **`platform_registry`**, **`platform_profile`**, **`resolution_state`**, **`resolver_stake_vault`**. Use **`category_id == 0`** for uncategorized markets (omit **`market_category`** account). Non-zero **`category_id`** requires an active **`market_category`** PDA for that platform.
|
|
594
594
|
|
|
595
595
|
Use **`derivePlatformRegistry`**, **`derivePlatformProfile`**, **`deriveMarketCategory`**, **`deriveResolutionState`**, **`deriveResolverStakeVault`** when building instructions manually.
|
|
596
596
|
|
|
@@ -598,8 +598,8 @@ Use **`derivePlatformRegistry`**, **`derivePlatformProfile`**, **`deriveMarketCa
|
|
|
598
598
|
|
|
599
599
|
Use `marketType: 'parimutuel'` or `'completeSet'` at creation; the choice is permanent.
|
|
600
600
|
|
|
601
|
-
- **Parimutuel
|
|
602
|
-
- **Complete-set
|
|
601
|
+
- **Parimutuel**, pooled stakes, no outcome SPLs; good default for prediction apps. **`isEarlyWithdrawAllowed`** is set at create (default **allowed**) and can be changed by the creator via **`updateParimutuelState`**; when disabled, early **`parimutuelWithdraw`** is blocked until close or resolution. **`maxWalletOutcomeInvestment`** and **`isWalletOutcomeStakeExact`** are set at create and can be updated via **`updateParimutuelState`** (same instruction as penalty / early-withdraw edits). After **`voidMarket`**, participants **`parimutuelWithdraw`** full net stakes (no penalty / withdraw fees).
|
|
602
|
+
- **Complete-set**, outcome SPL tokens; you still need external liquidity for single-leg trading.
|
|
603
603
|
|
|
604
604
|
## PDA helpers
|
|
605
605
|
|
package/agents/skill.md
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
# Vercora Protocol
|
|
1
|
+
# Vercora Protocol: agent skill entry (`@vercora-protocol/sdk`)
|
|
2
2
|
|
|
3
3
|
This file ships **inside** the npm package (`agents/skill.md`) so AI agents, clawbots, and operator scripts can load instructions without depending on a particular website.
|
|
4
4
|
|
|
5
|
+
**Scope:** Vercora Protocol is **multi-product issuer infrastructure** over time. **This skill and the bundled SDK** target the **outcome markets** program only (markets, resolution, settlement). Do not assume other product lanes (e.g. issuer diversification) are available in `PredictionMarketClient` until documented in this package.
|
|
6
|
+
|
|
5
7
|
## Public production deployment (Vercora)
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
When you **do not** have the monorepo, the canonical HTTPS deployment is **[vercora.xyz](https://vercora.xyz)**. Fetch these over TLS; use a Solana `Connection` and cluster that match the deployment you operate against (see this package’s `README.md`).
|
|
8
10
|
|
|
9
11
|
| Resource | URL |
|
|
10
12
|
|----------|-----|
|
|
11
13
|
| Full AI playbook (markdown) | `https://vercora.xyz/agents/playbook.md` |
|
|
12
14
|
| This skill entry (markdown) | `https://vercora.xyz/agents/skill.md` |
|
|
13
15
|
| Pointer manifest (JSON) | `https://vercora.xyz/.well-known/vercora-agents.json` |
|
|
14
|
-
| Developer docs (human) | `https://vercora.xyz/docs` (includes **Resolution flow
|
|
15
|
-
| AI / agents playbook (human + markdown) | `https://vercora.xyz/docs/agents
|
|
16
|
+
| Developer docs (human) | `https://vercora.xyz/docs` (includes **Resolution flow**, same narrative as agents) |
|
|
17
|
+
| AI / agents playbook (human + markdown) | `https://vercora.xyz/docs/agents`, full playbook + **resolution at a glance** |
|
|
16
18
|
|
|
17
19
|
Example:
|
|
18
20
|
|
|
@@ -26,8 +28,8 @@ For self-hosted or staging sites, use the same path suffixes with your origin: `
|
|
|
26
28
|
|
|
27
29
|
## What to read first
|
|
28
30
|
|
|
29
|
-
1. **This package’s `README.md
|
|
30
|
-
2. **Human playbook UI**
|
|
31
|
+
1. **This package’s `README.md`**: install, exports, `PredictionMarketClient` API, and the **AI agent integration** section (workflow map).
|
|
32
|
+
2. **Human playbook UI** at **`https://vercora.xyz/docs/agents`**: same playbook as below, plus a **Resolution at a glance** block (vote → propose → challenge → **confirm or refute-accept**), aligned with **`https://vercora.xyz/docs#resolution-flow`**.
|
|
31
33
|
3. **Full playbook** (skills, pitfalls, decision trees):
|
|
32
34
|
- **Production:** `https://vercora.xyz/agents/playbook.md`
|
|
33
35
|
- **Monorepo (contributors):** `prediction_market/docs/AI-AGENT-SDK-PLAYBOOK.md` (content matches the production mirror).
|
|
@@ -70,20 +72,20 @@ Paths are under `node_modules/@vercora-protocol/sdk/` after install.
|
|
|
70
72
|
## Quick guardrails (parimutuel)
|
|
71
73
|
|
|
72
74
|
- **`updateConfig`:** `params.secondaryAuthority` is written to chain on **every** call. When only adjusting fees/treasury, pass the **existing** secondary pubkey to keep (from `fetchGlobalConfig()`). Passing the primary key there removes the backup authority.
|
|
73
|
-
- After `fetchMarket(marketPda)`, read **`isEarlyWithdrawAllowed`**. If `false`, do not propose early-exit **`parimutuelWithdraw`** until close
|
|
75
|
+
- After `fetchMarket(marketPda)`, read **`isEarlyWithdrawAllowed`**. If `false`, do not propose early-exit **`parimutuelWithdraw`** until close or resolution (you hit **`EarlyWithdrawNotAllowed`**). If **`isVoided`**, **`parimutuelWithdraw`** still refunds full net stakes (no penalty / withdraw fees).
|
|
74
76
|
- Also read **`maxWalletOutcomeInvestment`** (`BN`, `0` = unlimited) and **`isWalletOutcomeStakeExact`**. When proposing **`parimutuelStake`**, enforce per-wallet caps and exact-stake rules (**`WalletOutcomeInvestmentCapExceeded`**, **`WalletOutcomeExactStakeMismatch`**).
|
|
75
|
-
- **Creators** (open pari market, not resolved/voided): **`updateParimutuelState`** updates penalty bps, **`isEarlyWithdrawAllowed`**, **`maxWalletOutcomeInvestment`**, and **`isWalletOutcomeStakeExact`** in one instruction
|
|
77
|
+
- **Creators** (open pari market, not resolved/voided): **`updateParimutuelState`** updates penalty bps, **`isEarlyWithdrawAllowed`**, **`maxWalletOutcomeInvestment`**, and **`isWalletOutcomeStakeExact`** in one instruction. Always pass **full** params (current values from **`fetchMarket`** + **`fetchParimutuelState`** for fields you keep unchanged). If **`isWalletOutcomeStakeExact`** is `true`, **`maxWalletOutcomeInvestment`** must be **> 0** (**`InvalidWalletOutcomeStakeExactConfig`** otherwise).
|
|
76
78
|
- **`voidMarket`:** the **creator** cannot void while pari **outcome pools** (active stakes) or complete-set outstanding is non-zero (**`CreatorCannotVoidWithActiveLiquidity`**). **Cannot void while an `openRefute` dispute is active** (**`CannotVoidWithOpenDispute`**). Propose a **global config authority** wallet to cancel live markets; SDK passes **`resolutionState`** and **`parimutuelState`** (pari) or `null` (complete-set).
|
|
77
|
-
- **`claimVoidedParimutuelSurplus`:** **global authority only
|
|
78
|
-
- Use **`isClosedEarly`**, **`isVoided`**, **`winningOutcomeIndex`** for lifecycle
|
|
79
|
+
- **`claimVoidedParimutuelSurplus`:** **global authority only**. If a voided pari market has **zero outcome stakes** but **`total_pool` > 0** (early-exit pool-keep left in the vault), sweep that surplus to the platform treasury. Call after users have finished void refunds.
|
|
80
|
+
- Use **`isClosedEarly`**, **`isVoided`**, **`winningOutcomeIndex`** for lifecycle, not legacy `closed` / `voided` / `resolvedOutcomeIndex` names.
|
|
79
81
|
|
|
80
82
|
## Quick guardrails (resolution)
|
|
81
83
|
|
|
82
84
|
- **`create_market`** requires **`platform_id > 0`**: register a platform, **`upsert_platform_profile`** (global config primary or secondary authority signs), and pass **`platform_registry`**, **`platform_profile`**, **`resolution_state`**, **`resolver_stake_vault`** (SDK methods wire PDAs when you use `PredictionMarketClient`).
|
|
83
85
|
- Settlement is **two-phase**: **`finalizeResolution`** records a **proposal** on **`fetchResolutionState`** (`proposed_outcome`, `proposal_ts`). It does **not** set **`winningOutcomeIndex`** on the market.
|
|
84
86
|
- After **`challenge_window_secs`** from **`fetchPlatformProfile(platformId)`** (same value used on-chain for the challenge window), call **`confirmResolution`** to finalize **`Market.winningOutcomeIndex`**. Until then, traders cannot **`redeemWinning`** / **`parimutuelClaim`** as “resolved.”
|
|
85
|
-
- Optional dispute: **`openRefute`** during the window; **`resolveRefute`** with **`accept: false`** slashes the bond to treasury, **`accept: true`** refunds the refuter and sets **`winningOutcomeIndex`** immediately. **Who signs `resolveRefute`:** global **primary/secondary** (`GlobalConfig`) or platform **`profileAuthority`** on **`PlatformRegistry
|
|
86
|
-
- **`disputer_collateral`** on **`resolve_refute`**: the refuter’s collateral ATA (same role as **`refuter_collateral`** on **`open_refute`**). **Always** in the account list
|
|
87
|
-
- **`claim_resolver_stake`** / **`resolve_refute`**: if **`platform_fee_lamports` > 0**, the program transfers SOL to **`platform_treasury_wallet
|
|
87
|
+
- Optional dispute: **`openRefute`** during the window; **`resolveRefute`** with **`accept: false`** slashes the bond to treasury, **`accept: true`** refunds the refuter and sets **`winningOutcomeIndex`** immediately. **Who signs `resolveRefute`:** global **primary/secondary** (`GlobalConfig`) or platform **`profileAuthority`** on **`PlatformRegistry`**, **not** the per-market **`voteResolution`** resolver wallets. Legacy **`dispute_resolution_authority`** on config does **not** gate this instruction. **`confirmResolution`** fails while a dispute blocks it; skip **`confirmResolution`** if accept already finalized the market.
|
|
88
|
+
- **`disputer_collateral`** on **`resolve_refute`**: the refuter’s collateral ATA (same role as **`refuter_collateral`** on **`open_refute`**). **Always** in the account list. **Dismiss** does not transfer the bond into it, but the account must still be present and valid. Raw Anchor: use camelCase **`disputerCollateral`** in `.accounts()` or Anchor reports **Account disputerCollateral not provided**. Prefer the **IDL from `@vercora-protocol/sdk`** (`import { IDL } …` or `dist/idl/vercora.json`); a separately hosted / `fetchIdl` JSON that drifts from the package causes the same error.
|
|
89
|
+
- **`claim_resolver_stake`** / **`resolve_refute`**: if **`platform_fee_lamports` > 0**, the program transfers SOL to **`platform_treasury_wallet`**. The IDL must mark that wallet **writable** or you can hit **PrivilegeEscalation** (“writable privilege escalated”). Use the published package IDL; do not strip `writable` when forking JSON.
|
|
88
90
|
- After final winner is set, resolvers may **`claimResolverStake`** (wrong outcome → slash to treasury). Read **`fetchResolutionState`** + **`fetchMarket`** together for UI (proposal vs final).
|
|
89
91
|
- **Tooling:** **`SendTransactionError: Unknown action 'undefined'`** can appear with some **`@coral-xyz/anchor`** + **`@solana/web3.js`** pairs (error ctor mismatch). Stay on the SDK **`package.json`** peer ranges or align **`@solana/web3.js`** with Anchor’s guidance for your Anchor minor.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercora-protocol/sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "TypeScript SDK for the
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "TypeScript SDK for Vercora Protocol on Solana — client for the outcome-markets Anchor program (issuer utility infra; more product lanes on the roadmap).",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"files": [
|