Skip to content
This repository was archived by the owner on May 11, 2026. It is now read-only.

Feature: redeem positions#187

Open
Lekky71 wants to merge 7 commits into
Polymarket:mainfrom
Lekky71:feature/redeem-positions
Open

Feature: redeem positions#187
Lekky71 wants to merge 7 commits into
Polymarket:mainfrom
Lekky71:feature/redeem-positions

Conversation

@Lekky71
Copy link
Copy Markdown

@Lekky71 Lekky71 commented Oct 6, 2025

Hi guys, awesome work you folks have been doing, I'm a big fan!

I spent some time over the weekend building automation around Polymarket and realized that there was no ClobClient function to redeem positions (Googled and saw folks asking for it as well) which if you ask me it allows folks to easily move their winnings and keep on trading, I would imagine before now people just interacted with CTF contract directly but to make things a bit easier I added a comprehensive position redemption feature for resolved markets, supporting both EOA and Safe/Proxy wallet types with proper gas handling and EIP-712 signature generation.

My code structure may not be inline with yours so please do let me know so I can make changes. I used the functions on my end and they work smoothly.

Core Features

BlockchainClient Enhancements

  • Extracted getSafeTransactionHash and generateSafeSignatureFromHash as standalone utility functions for testability
  • Added redeemMarketPositionsForEOA for standard wallet redemption
  • Added redeemMarketPositionsForSafeWallet for Safe/Proxy wallet redemption with proper EIP-712 transaction hash generation and signature approval
  • Implemented getCurrentFeeParams with Polygon network minimum gas requirements (80 gwei) to prevent transaction failures
  • Added approveHashOnSafe for on-chain hash approval before execution

Helper Function Updates

  • Added redeemMarketPositions wrapper function to route redemption requests based on signature type (EOA vs Safe wallet)
  • Validated funderWalletAddress requirement for Safe wallet redemptions

Type Definitions

  • Added RedeemMarketPositionsParams interface
  • Added RedeemMarketPositionsForSafeWalletParams interface
  • Added ApproveHashOnSafeParams interface
  • Added SafeTransactionHashParams interface with bigint types for numeric fields

ClobClient Integration

  • Added redeemPositions method to ClobClient for easy redemption access
  • Automatically routed to appropriate redemption method based on signature type
  • Passed through funder address when using Safe wallets

Testing

  • Added comprehensive tests for getSafeTransactionHash covering:
    • Hash consistency for same inputs
    • Different hashes for different parameters (address, nonce, chain, data)
  • Added tests for generateSafeSignatureFromHash validating:
    • Signature consistency
    • Different signatures for different inputs
    • Correct v=1 encoding for approved hash type
    • Proper owner address encoding as r parameter
  • Added 7 test cases for redeemPositions helper function covering all wallet types

Examples

  • Created examples/redeemMarketPositions.ts with two example functions:
    • redeemForEOA(): Standard wallet redemption example
    • redeemForProxy(): Safe/Proxy wallet redemption example
  • Included proper environment setup, error handling, and transaction logging

Technical Implementation

  • Used ethers v5 BigNumber API throughout for gas calculations
  • Implemented EIP-712 structured data hashing for Safe transactions
  • Used approved hash signature type (v=1) for Polymarket Safe compatibility
  • Set minimum gas fees to 80 gwei to meet Polygon network requirements (I also tested during high congestion period, hence this value)

Breaking Changes

None - all additions were backwards compatible


Note

Adds market position redemption support

  • New BlockchainClient with redeemMarketPositionsForEOA and redeemMarketPositionsForSafeWallet (Safe EIP-712 hash/signature + on-chain approve flow); includes getSafeTransactionHash and generateSafeSignatureFromHash
  • Introduces ABIs src/blockchain/abi/ctf.abi.ts and src/blockchain/abi/safe.abi.ts
  • Exposes ClobClient.redeemPositions routed via helper redeemMarketPositions (handles SignatureType and Safe funder address)
  • Adds gas config constants (REDEEM_POSITIONS_GAS_LIMIT, REDEEM_POSITIONS_MINIMUM_MAX_FEE) in config.ts
  • Tests for hash/signature utilities and redemption helper; example script examples/redeemMarketPositions.ts

Written by Cursor Bugbot for commit af8a2d0. This will update automatically on new commits. Configure here.

Add comprehensive position redemption feature for resolved markets, supporting
  both EOA and Safe/Proxy wallet types with proper gas handling and EIP-712
  signature generation.

  ## Core Features

  ### BlockchainClient Enhancements
  - Extract `getSafeTransactionHash` and `generateSafeSignatureFromHash` as
    standalone utility functions for testability
  - Add `redeemMarketPositionsForEOA` for standard wallet redemption
  - Add `redeemMarketPositionsForSafeWallet` for Safe/Proxy wallet redemption
    with proper EIP-712 transaction hash generation and signature approval
  - Implement `getCurrentFeeParams` with Polygon network minimum gas requirements
    (80 gwei) to prevent transaction failures
  - Add `approveHashOnSafe` for on-chain hash approval before execution

  ### Helper Function Updates
  - Add `redeemMarketPositions` wrapper function to route redemption requests
    based on signature type (EOA vs Safe wallet)
  - Validate `funderWalletAddress` requirement for Safe wallet redemptions

  ### Type Definitions
  - Add `RedeemMarketPositionsParams` interface
  - Add `RedeemMarketPositionsForSafeWalletParams` interface
  - Add `ApproveHashOnSafeParams` interface
  - Add `SafeTransactionHashParams` interface with bigint types for numeric fields

  ### ClobClient Integration
  - Add `redeemPositions` method to ClobClient for easy redemption access
  - Automatically route to appropriate redemption method based on signature type
  - Pass through funder address when using Safe wallets

  ### Testing
  - Add comprehensive tests for `getSafeTransactionHash` covering:
    - Hash consistency for same inputs
    - Different hashes for different parameters (address, nonce, chain, data)
  - Add tests for `generateSafeSignatureFromHash` validating:
    - Signature consistency
    - Different signatures for different inputs
    - Correct v=1 encoding for approved hash type
    - Proper owner address encoding as r parameter
  - Add 7 test cases for `redeemPositions` helper function covering all wallet types

  ### Examples
  - Create `examples/redeemMarketPositions.ts` with two example functions:
    - `redeemForEOA()`: Standard wallet redemption example
    - `redeemForProxy()`: Safe/Proxy wallet redemption example
  - Include proper environment setup, error handling, and transaction logging

  ## Technical Implementation

  - Use ethers v5 BigNumber API throughout for gas calculations
  - Implement EIP-712 structured data hashing for Safe transactions
  - Use approved hash signature type (v=1) for Polymarket Safe compatibility
  - Set minimum gas fees to 80 gwei to meet Polygon network requirements
  - Add extensive console logging for debugging Safe transaction flow

  ## Breaking Changes
  None - all additions are backwards compatible
… feature/redeem-positions

# Conflicts:
#	src/client.ts
@Lekky71 Lekky71 requested a review from a team as a code owner October 6, 2025 22:22
Copilot AI review requested due to automatic review settings October 6, 2025 22:22
@Lekky71 Lekky71 changed the title Feature/redeem positions Feature: redeem positions Oct 6, 2025
cursor[bot]

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a comprehensive position redemption feature for the Polymarket ClobClient, enabling users to easily redeem winning positions from resolved markets. The implementation supports both EOA (Externally Owned Account) wallets and Safe/Proxy wallets commonly used by Polymarket accounts.

  • Adds complete blockchain client functionality for position redemption with proper gas handling and Safe wallet EIP-712 signature generation
  • Implements helper functions and ClobClient integration to route redemption requests based on signature type
  • Provides comprehensive test coverage and example implementations for both wallet types

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/blockchain/blockchain.client.ts Core blockchain client with EOA and Safe wallet redemption methods, gas handling, and EIP-712 signature utilities
src/blockchain/abi/ctf.abi.ts Conditional Token Framework ABI for contract interactions
src/blockchain/abi/safe.abi.ts Safe wallet ABI for transaction execution and nonce management
src/order-builder/helpers.ts Helper function to route redemption requests based on signature type with validation
src/client.ts ClobClient integration adding redeemPositions method with authentication checks
src/types.ts Type definitions for redemption parameters and Safe transaction structures
tests/blockchain/blockchain.client.test.ts Comprehensive unit tests for Safe transaction hash generation and signature functions
tests/order-builder/helpers.test.ts Tests for redemption helper function covering all wallet types and error cases
examples/redeemMarketPositions.ts Usage examples for both EOA and Safe wallet redemption scenarios

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment thread src/client.ts Outdated
Comment thread src/blockchain/blockchain.client.ts Outdated
Comment thread src/blockchain/blockchain.client.ts Outdated
Comment thread tests/order-builder/helpers.test.ts Outdated
Comment thread tests/order-builder/helpers.test.ts Outdated
Copilot AI review requested due to automatic review settings October 13, 2025 18:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (2)

src/blockchain/blockchain.client.ts:1

  • The SafeTransactionHashParams interface accepts both number and bigint types, but the implementation only handles bigint values. This could lead to runtime errors if number values are passed. Consider using only bigint for consistency with ethers.js BigNumber usage.
import { ethers } from "ethers";

src/blockchain/blockchain.client.ts:1

  • The SafeTransactionHashParams interface accepts both number and bigint types, but the implementation only handles bigint values. This could lead to runtime errors if number values are passed. Consider using only bigint for consistency with ethers.js BigNumber usage.
import { ethers } from "ethers";

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment thread examples/redeemMarketPositions.ts
Comment thread examples/redeemMarketPositions.ts
@mys3lf
Copy link
Copy Markdown

mys3lf commented Nov 18, 2025

Hey everybody. I would like to use this feature. Is there anything that speaks against a merge?

@willvx3m
Copy link
Copy Markdown

@Lekky71 Man, this is a great PR. could you also make one for fetching redeemable positions so we can directly combine with this?

@Narenthirasamy
Copy link
Copy Markdown

@Lekky71 Maybe merge conflict fix would consider the team to review again.

Comment thread src/types.ts Outdated

// Blockchain Client Types
export interface RedeemMarketPositionsParams {
ConditionID: string;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, I would use conditionId to be consistent with the casing

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sure.

Comment on lines +398 to +421
export const redeemMarketPositions = (
eoaSigner: Wallet | JsonRpcSigner,
chainId: Chain,
signatureType: SignatureType,
params: {
ConditionID: string;
funderWalletAddress?: string;
},
): Promise<TransactionReceipt> => {
const blockchainClient = new BlockchainClient(eoaSigner, chainId);
if (signatureType === SignatureType.EOA) {
return blockchainClient.redeemMarketPositionsForEOA({
ConditionID: params.ConditionID,
});
}
if (!params.funderWalletAddress) {
throw new Error("funderWalletAddress is required for Safe wallet redemption");
}

return blockchainClient.redeemMarketPositionsForSafeWallet({
ConditionID: params.ConditionID,
safeWalletAddress: params.funderWalletAddress,
});
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • guess we could provide possibility to accept multiple conditions to process...something like
export const redeemMarketPositions = async (
    eoaSigner: Wallet | JsonRpcSigner,
    chainId: Chain,
    signatureType: SignatureType,
    params: {
        ConditionID: string | string[]; // Accept single or array
        funderWalletAddress?: string;
    },
): Promise<TransactionReceipt | TransactionReceipt[]> => {
    const blockchainClient = new BlockchainClient(eoaSigner, chainId);
    const conditionIds = Array.isArray(params.ConditionID) 
        ? params.ConditionID 
        : [params.ConditionID];
    
    const redeemPromises = conditionIds.map(conditionId => {
        if (signatureType === SignatureType.EOA) {
            return blockchainClient.redeemMarketPositionsForEOA({
                ConditionID: conditionId,
            });
        }
        if (!params.funderWalletAddress) {
            throw new Error("funderWalletAddress is required for Safe wallet redemption");
        }
        return blockchainClient.redeemMarketPositionsForSafeWallet({
            ConditionID: conditionId,
            safeWalletAddress: params.funderWalletAddress,
        });
    });
    
    const receipts = await Promise.all(redeemPromises);
    
    // Return single receipt if single condition, array if multiple
    return Array.isArray(params.ConditionID) ? receipts : receipts[0];
};

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably best to keep as is.

… feature/redeem-positions

# Conflicts:
#	src/client.ts
#	src/order-builder/helpers.ts
#	src/types.ts
#	tests/order-builder/helpers.test.ts
@Lekky71
Copy link
Copy Markdown
Author

Lekky71 commented Dec 31, 2025

@Lekky71 Man, this is a great PR. could you also make one for fetching redeemable positions so we can directly combine with this?

Thank you, good idea, can come in another PR.

@Lekky71 Lekky71 requested a review from davscro December 31, 2025 01:10
contractConfig.collateral,
ethers.constants.HashZero,
params.ConditionID,
[1, 2],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Lekky71 could you please check this?

ConditionID: params.ConditionID,
safeWalletAddress: params.funderWalletAddress,
});
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Lekky71 please check this one as well 🙏

@davscro
Copy link
Copy Markdown

davscro commented Dec 31, 2025

@Lekky71 Man, this is a great PR. could you also make one for fetching redeemable positions so we can directly combine with this?

@willvx3m you can always get those positions using redeemable=true by documentation

ie -> https://data-api.polymarket.com/positions?user=0x16b29c50f2439faf627209b2ac0c7bbddaa8a881&redeemable=true

*NOTE - but keep in mind there you will also get the lost positions as well

@willvx3m
Copy link
Copy Markdown

Do we have estimated timeline when this can get merged?

@willvx3m
Copy link
Copy Markdown

willvx3m commented Feb 12, 2026

@davscro Thanks for your last comment.
Could you advice how we can use this SDK for deposit/withdrawal as well? I see a documentation page (Bridge -> Quote) for that, but not quite sure about execution. If you could provide code sample, that'd be awesome!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants