Skip to content

Conversation

@spacesailor24
Copy link
Contributor

@spacesailor24 spacesailor24 commented Nov 14, 2025

Description

  • Both precheck and execute now ensure that the Agent Wallet’s PKP has granted the required Hyperliquid Builder Fee permission (hardcoded at 0.05%) for our Vincent Builder address whenever the Ability Action is spotSell, perpLong, or perpShort

    • If this Builder Fee is not permitted, precheck will fail for these three actions
    • execute will automatically grant the required permission for these three actions, before executing the action
  • A new Ability action was added: approveBuilderCode

    • For this action, precheck will fail if already permitted
    • execute will permit it even if already permitted
  • Setup code for all E2E tests was standardized

  • Some missing response types for various Ability actions are now exported

  • Docs will be updated in a fast follow PR

Type of change

Although maybe this is a breaking change?

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

  • test/e2e/perp/long.spec.ts, test/e2e/perp/short.spec.ts, and test/e2e/spot/sell.spec.ts were updated to check the HL Builder reward balance before executing their E2E tests, and then after to validate the reward balance increased
  • New test: test/e2e/approve-builder-code.spec.ts was added to validate explicitly permitting the HL Builder works

The following are the E2E test commands and their success output:

pnpx nx run ability-hyperliquid:test-e2e packages/apps/ability-hyperliquid/test/e2e/approve-builder-code.spec.ts

Before initial permit:

[Approve Builder Code Execute] {
  success: true,
  result: {
    action: 'approveBuilderCode',
    approveResult: { status: 'ok', response: { type: 'default' } }
  },
  context: {
    delegation: {
      delegateeAddress: '0xb50aBA1E265B52067aF97401C25C39efF57Fe83b',
      delegatorPkpInfo: {
        tokenId: '35617002763746774873624099358656207007678734435252619904988836854182795624385',
        ethAddress: '0x5C27297F341d6564Da9a8bB3481e9e2a54744284',
        publicKey: '0x047184d980c1c00dbb3d48e7aae2eb268e1ce06b13b22c6242015299f025a5735f318de5811f8de4775a7477c8653b685c739d06bd26334b3e0dd2afcd0d700b5b'
      }
    },
    abilityIpfsCid: 'QmeRz1hh6ejpaXiK2JDJbWpcNbAQvd4BzYgHCFErxGMCfS',
    appId: 47700028661,
    appVersion: 28,
    policiesContext: { allow: true, evaluatedPolicies: [], allowedPolicies: {} }
  }
}
[Approve Builder Code] Initial approval status: false
[Approve Builder Code] Final approval status: true

After permitted:

AbilityConfig precheck result {"success":false,"result":{"action":"approveBuilderCode","reason":"Builder code 0x132Db5f531Ba38628F1640683354229daE04E8e6 is already approved"}}

  at Object.precheck (../../libs/ability-sdk/dist/src/lib/abilityCore/vincentAbility.js:123:25)

console.log
precheckResult() {"success":false,"result":{"action":"approveBuilderCode","reason":"Builder code 0x132Db5f531Ba38628F1640683354229daE04E8e6 is already approved"}}

  at Object.precheck (../../libs/app-sdk/dist/src/abilityClient/vincentAbilityClient.js:167:21)

console.log
[Approve Builder Code Precheck] {
  success: false,
  runtimeError: undefined,
  result: {
    action: 'approveBuilderCode',
    reason: 'Builder code 0x132Db5f531Ba38628F1640683354229daE04E8e6 is already approved'
  },
  context: {
    delegation: {
      delegateeAddress: '0xb50aBA1E265B52067aF97401C25C39efF57Fe83b',
      delegatorPkpInfo: {
        tokenId: '35617002763746774873624099358656207007678734435252619904988836854182795624385',
        ethAddress: '0x5C27297F341d6564Da9a8bB3481e9e2a54744284',
        publicKey: '0x047184d980c1c00dbb3d48e7aae2eb268e1ce06b13b22c6242015299f025a5735f318de5811f8de4775a7477c8653b685c739d06bd26334b3e0dd2afcd0d700b5b'
      }
    },
    abilityIpfsCid: 'QmeRz1hh6ejpaXiK2JDJbWpcNbAQvd4BzYgHCFErxGMCfS',
    appId: 47700028661,
    appVersion: 28,
    rpcUrl: undefined,
    policiesContext: { allow: true, evaluatedPolicies: [], allowedPolicies: {} }
  }
}
[Approve Builder Code] Builder code is already approved, skipping execution test
[Approve Builder Code] Initial approval status: true
[Approve Builder Code] Final approval status: true

pnpx nx run ability-hyperliquid:test-e2e packages/apps/ability-hyperliquid/test/e2e/spot/sell.spec.ts
[Spot Sell] Referral data after sell: {
  referredBy: null,
  cumVlm: '0.0',
  unclaimedRewards: '0.052903',
  claimedRewards: '0.0',
  builderRewards: '0.052903',
  referrerState: { stage: 'needToTrade', data: { required: '10000.0' } },
  rewardHistory: [],
  tokenToState: [
    [
      0,
      {
        cumVlm: '0.0',
        unclaimedRewards: '0.052903',
        claimedRewards: '0.0',
        builderRewards: '0.052903'
      }
    ]
  ]
}
[Spot Sell] Initial builder rewards: 0.047845
[Spot Sell] Final builder rewards: 0.052903
[Spot Sell] Builder rewards increased by: 0.005058

pnpx nx run ability-hyperliquid:test-e2e packages/apps/ability-hyperliquid/test/e2e/perp/long.spec.ts
[Perp Long] Referral data after long: {
  referredBy: null,
  cumVlm: '0.0',
  unclaimedRewards: '0.059987',
  claimedRewards: '0.0',
  builderRewards: '0.059987',
  referrerState: { stage: 'needToTrade', data: { required: '10000.0' } },
  rewardHistory: [],
  tokenToState: [
    [
      0,
      {
        cumVlm: '0.0',
        unclaimedRewards: '0.059987',
        claimedRewards: '0.0',
        builderRewards: '0.059987'
      }
    ]
  ]
}
[Perp Long] Initial builder rewards: 0.052903
[Perp Long] Final builder rewards: 0.059987
[Perp Long] Builder rewards increased by: 0.007084

pnpx nx run ability-hyperliquid:test-e2e packages/apps/ability-hyperliquid/test/e2e/perp/short.spec.ts
[Perp Short] Referral data after short: {
  referredBy: null,
  cumVlm: '0.0',
  unclaimedRewards: '0.067054',
  claimedRewards: '0.0',
  builderRewards: '0.067054',
  referrerState: { stage: 'needToTrade', data: { required: '10000.0' } },
  rewardHistory: [],
  tokenToState: [
    [
      0,
      {
        cumVlm: '0.0',
        unclaimedRewards: '0.067054',
        claimedRewards: '0.0',
        builderRewards: '0.067054'
      }
    ]
  ]
}
[Perp Short] Initial builder rewards: 0.059987
[Perp Short] Final builder rewards: 0.067054
[Perp Short] Builder rewards increased by: 0.007067000000000004

Checklist:

  • I created a release plan (nx release plan) describing my changes and the version bump
  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

@vercel
Copy link

vercel bot commented Nov 14, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
vincent-app-dashboard Ready Ready Preview Comment Nov 18, 2025 4:30am

Copy link
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 adds Hyperliquid builder fee support to spot sell and perpetual (long/short) orders, enabling the collection of 0.05% builder fees. The implementation includes automatic approval of builder codes during execution, a new approveBuilderCode action for explicit approval, and comprehensive E2E test coverage validating builder reward accrual.

Key Changes

  • Implements automatic builder code approval with 0.05% fee for spotSell, perpLong, and perpShort actions
  • Adds new approveBuilderCode ability action with corresponding precheck and execute logic
  • Standardizes E2E test setup using setupVincentDevelopmentEnvironment helper function

Reviewed Changes

Copilot reviewed 31 out of 33 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/lib/vincent-ability.ts Adds builder fee approval checks in precheck, automatic approval in execute, and fee configuration for spot/perp orders
src/lib/constants.ts Defines Vincent builder address and 0.05% fee rate constants
src/lib/types.ts Adds APPROVE_BUILDER_CODE enum value to HyperliquidAction
src/lib/schemas.ts Adds schema validation for approveBuilderCode action and result
src/lib/ability-helpers/approve-builder-code.ts Implements builder code approval via EIP-712 signed action
src/lib/ability-helpers/execute-spot-order.ts Adds optional builder fee parameter for spot sell orders
src/lib/ability-helpers/execute-perp-order.ts Adds optional builder fee parameter for perpetual orders
src/lib/ability-checks/is-builder-code-approved.ts Implements check for existing builder code approval status
test/e2e/approve-builder-code.spec.ts New E2E test validating explicit builder code approval
test/e2e/spot/sell.spec.ts Validates builder rewards increase after spot sell execution
test/e2e/perp/long.spec.ts Validates builder rewards increase after perp long execution
test/e2e/perp/short.spec.ts Validates builder rewards increase after perp short execution
Multiple E2E test files Standardizes test setup using setupVincentDevelopmentEnvironment helper

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings November 14, 2025 20:10
Copy link
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 31 out of 33 changed files in this pull request and generated 13 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings November 18, 2025 04:27
Copy link
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 31 out of 33 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

*/
builderFee?: {
builderAddress: string; // Builder address
feeInTenthsOfBps: number; // Fee in tenths of basis points (e.g., 50 = 0.05%)
Copy link

Copilot AI Nov 18, 2025

Choose a reason for hiding this comment

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

The comment is inconsistent with line 27. Line 27 correctly states '50 = 0.05% = 5 basis points' but line 32 only says '50 = 0.05%' without clarifying the basis points. For consistency and clarity, update line 32 to match the format on line 27: // Fee in tenths of basis points (e.g., 50 = 0.05% = 5 basis points)

Suggested change
feeInTenthsOfBps: number; // Fee in tenths of basis points (e.g., 50 = 0.05%)
feeInTenthsOfBps: number; // Fee in tenths of basis points (e.g., 50 = 0.05% = 5 basis points)

Copilot uses AI. Check for mistakes.
*/
builderFee?: {
builderAddress: string; // Builder address
feeInTenthsOfBps: number; // Fee in tenths of basis points (e.g., 10 = 0.01%)
Copy link

Copilot AI Nov 18, 2025

Choose a reason for hiding this comment

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

The comment should clarify the basis points conversion for consistency with spot orders. Update to: // Fee in tenths of basis points (e.g., 10 = 0.01% = 1 basis point) to match the documentation style on line 46.

Suggested change
feeInTenthsOfBps: number; // Fee in tenths of basis points (e.g., 10 = 0.01%)
feeInTenthsOfBps: number; // Fee in tenths of basis points (e.g., 10 = 0.01% = 1 basis point)

Copilot uses AI. Check for mistakes.
* (since 1% = 100 basis points = 1000 tenths of basis points)
*/
function percentageToTenthsOfBps(percentageStr: string): number {
const percentage = parseFloat(percentageStr);
Copy link

Copilot AI Nov 18, 2025

Choose a reason for hiding this comment

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

The function should validate the input to prevent invalid conversions. Add input validation to check if percentageStr is a valid numeric string and if parseFloat returns NaN. Consider: if (isNaN(percentage) || percentage < 0) { throw new Error('Invalid percentage value'); }

Suggested change
const percentage = parseFloat(percentageStr);
const percentage = parseFloat(percentageStr);
if (isNaN(percentage) || percentage < 0) {
throw new Error('Invalid percentage value');
}

Copilot uses AI. Check for mistakes.
it('should validate builder rewards increased after spot sell', async () => {
// Wait a bit for order to fill and builder rewards to be credited
// Builder rewards are processed onchain, so we need to wait for the transaction to be processed
await new Promise((resolve) => setTimeout(resolve, 10000));
Copy link

Copilot AI Nov 18, 2025

Choose a reason for hiding this comment

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

The hardcoded 10-second timeout is a magic number that could fail in slower network conditions or cause unnecessary delays in faster environments. Consider extracting this to a named constant like BUILDER_REWARD_PROCESSING_TIMEOUT_MS = 10000 or make it configurable via environment variable for different test environments.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants