Skip to content

0x v2 - #739

Merged
Dargon789 merged 13 commits into
masterfrom
0x-v2
Aug 16, 2026
Merged

0x v2#739
Dargon789 merged 13 commits into
masterfrom
0x-v2

Conversation

@Dargon789

@Dargon789 Dargon789 commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Summary by Sourcery

Integrate typed precondition support into the relayer and API client, enabling encoding and validation of on-chain balance, approval, and ownership conditions.

New Features:

  • Add relayer precondition module defining typed native, ERC20, ERC721, and ERC1155 balance, approval, and ownership conditions with validation and encoding to proto messages.
  • Extend the Sequence API client to work with the new proto API and expose utilities for validating and encoding chain preconditions, including chain ID handling.

Enhancements:

  • Update API client header handling to support more flexible header value types and re-export the generated API surface from the main entrypoint.

attente and others added 7 commits January 15, 2025 14:33
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
@bolt-new-by-stackblitz

Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@codesandbox

codesandbox Bot commented Aug 15, 2026

Copy link
Copy Markdown

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

@vercel

vercel Bot commented Aug 15, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
sequence-js-docs Ready Ready Preview Aug 16, 2026 9:40am
sequence-js-web Ready Ready Preview Aug 16, 2026 9:40am
sequence.js Ready Ready Preview Aug 16, 2026 9:40am
wagmi-project Ready Ready Preview Aug 16, 2026 9:40am

@sourcery-ai

sourcery-ai Bot commented Aug 15, 2026

Copy link
Copy Markdown

Reviewer's Guide

Introduce a typed precondition system for the relayer and API client, including runtime type guards and encoding helpers for protobuf RPC, while slightly adjusting the API client base import and request header typing.

File-Level Changes

Change Details Files
Refactor SequenceAPIClient to extend the generated proto API and add precondition helpers tied to chainId handling.
  • Switch base class from the older API RPC import to the namespaced proto.API from the updated generator
  • Relax request header type from Record<string,string> to an index signature allowing any header values
  • Re-export all generated API symbols from the new api.gen module
  • Add a composite Precondition type that augments relayer preconditions with a chainId field
  • Add isPrecondition type guard that validates chainId as BigNumberish and delegates to the relayer precondition guard
  • Add encodePrecondition utility that converts the extended Precondition into the protobuf Precondition format, removing chainId from the nested args and encoding it as a string
  • Introduce internal helpers isBigNumberish and encodeBigNumberish to validate/normalize ethers.BigNumberish inputs
packages/services/api/src/index.ts
Add a dedicated relayer precondition module defining supported precondition variants, runtime validators, and encoding logic to proto.Precondition.
  • Define a union Precondition type covering native balance, ERC20/721/1155 balance, ownership, and approval scenarios
  • Implement isPrecondition dispatcher that delegates to specific type guards for each precondition variant
  • For each precondition variant, define a strongly typed shape including address, token, operator, tokenId, min/max and optional flags
  • Implement per-variant isXXXPrecondition functions that validate object shape, Ethereum addresses via ethers.isAddress, and numeric fields via a BigNumberish guard
  • Implement per-variant encodeXXXPrecondition functions that map the typed preconditions into proto.Precondition, stripping the local type tag and encoding BigNumberish fields as decimal strings, including normalization of booleans (e.g., owned defaulting to true)
  • Add shared helpers isBigNumberish and encodeBigNumberish using ethers.toBigInt for runtime validation and conversion
packages/relayer/src/precondition.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@snyk-io

snyk-io Bot commented Aug 15, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 5 issues, and left some high level feedback:

  • Several isXPrecondition helpers (e.g. isErc721OwnershipPrecondition, isErc721ApprovalPrecondition) don't guard against null values while others do (precondition &&), which can cause runtime errors on null inputs; consider consistently checking for non-null objects before accessing properties.
  • The various encode*Precondition functions spread the input object and then set type: undefined, which still leaves a type key present on the encoded payload; if type should be omitted entirely from the nested precondition, consider using object rest or an explicit omit instead of assigning undefined.
  • In SequenceAPIClient._fetch, the headers object is typed as { [key: string]: any } even though the Fetch API expects string header values; tightening this to { [key: string]: string } (or a more precise type) would avoid unintentionally passing non-string values into fetch.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Several `isXPrecondition` helpers (e.g. `isErc721OwnershipPrecondition`, `isErc721ApprovalPrecondition`) don't guard against `null` values while others do (`precondition &&`), which can cause runtime errors on `null` inputs; consider consistently checking for non-null objects before accessing properties.
- The various `encode*Precondition` functions spread the input object and then set `type: undefined`, which still leaves a `type` key present on the encoded payload; if `type` should be omitted entirely from the nested `precondition`, consider using object rest or an explicit omit instead of assigning `undefined`.
- In `SequenceAPIClient._fetch`, the `headers` object is typed as `{ [key: string]: any }` even though the Fetch API expects string header values; tightening this to `{ [key: string]: string }` (or a more precise type) would avoid unintentionally passing non-string values into `fetch`.

## Individual Comments

### Comment 1
<location path="packages/services/api/src/index.ts" line_range="23" />
<code_context>
     // automatically include jwt and access key auth header to requests
     // if its been set on the api client
-    const headers: Record<string, string> = {}
+    const headers: { [key: string]: any } = {}

     const jwtAuth = this.jwtAuth
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Headers typing is overly permissive and loses the previous string-only constraint.

Changing from `Record<string, string>` to `{ [key: string]: any }` means header values are no longer guaranteed to be strings, which can cause unexpected coercions or subtle bugs when passing `headers` to `fetch`. If you need optional values, prefer a stricter type such as `Record<string, string | undefined>` or a more precise union instead of `any`.

Suggested implementation:

```typescript
    // automatically include jwt and access key auth header to requests
    // if its been set on the api client
    const headers: Record<string, string | undefined> = {}

```

If elsewhere in this file you are assigning non-string values to `headers` (e.g. numbers, booleans, objects), those assignments should be updated to `.toString()` or otherwise converted to strings to comply with the stricter type. Also ensure `headers` is actually wired into the `fetch` call (e.g. via `init = { ...init, headers }`), if that was the original intent of this helper.
</issue_to_address>

### Comment 2
<location path="packages/services/api/src/index.ts" line_range="54-55" />
<code_context>
+}
+
+export function encodePrecondition(precondition: Precondition): proto.Precondition {
+  const { type, precondition: args } = encodeChainPrecondition(precondition)
+  delete args.chainId
+  return { type, chainID: encodeBigNumberish(precondition.chainId), precondition: args }
+}
</code_context>
<issue_to_address>
**issue (bug_risk):** Avoid mutating the `args` object returned from `encodeChainPrecondition`.

`delete args.chainId` mutates the object from `encodeChainPrecondition`, which may be reused or assumed immutable. Instead, destructure to omit `chainId`, e.g. `const { chainId: _ignored, ...rest } = args`, and use `rest` when building the proto precondition to keep this function side-effect-free.
</issue_to_address>

### Comment 3
<location path="packages/services/api/src/index.ts" line_range="68-71" />
<code_context>
+  }
+}
+
+function encodeBigNumberish<T extends ethers.BigNumberish | undefined>(
+  value: T
+): T extends ethers.BigNumberish ? string : undefined {
+  return value !== undefined ? ethers.toBigInt(value).toString() : (undefined as any)
+}
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Generic return typing plus `(undefined as any)` is misleading and undermines type safety.

The conditional return type coupled with `undefined as any` lets callers assume types that don’t match runtime behavior. Prefer a simple `encodeBigNumberish(value: ethers.BigNumberish | undefined): string | undefined` to keep types aligned with the implementation, or use overloads if you truly need distinct call signatures.

Suggested implementation:

```typescript
function isBigNumberish(value: any): value is ethers.BigNumberish {
  try {
    ethers.toBigInt(value)
    return true
  } catch {
    return false
  }
}

function encodeBigNumberish(value: ethers.BigNumberish | undefined): string | undefined {
  return value !== undefined ? ethers.toBigInt(value).toString() : undefined
}

```

```typescript
export * from './api.gen'

export type Precondition = { chainId: ethers.BigNumberish } & ChainPrecondition

export function isPrecondition(precondition: any): precondition is Precondition {
  return (
    typeof precondition === 'object' && precondition && isBigNumberish(precondition.chainId) && isChainPrecondition(precondition)
  )
}

```

If there are call sites that relied on the generic conditional return type (e.g., expecting `string` when passing a non-`undefined` type argument), they may need minor type adjustments to accept `string | undefined` or, if necessary, explicit non-null assertions after appropriate runtime checks.
</issue_to_address>

### Comment 4
<location path="packages/relayer/src/precondition.ts" line_range="143-150" />
<code_context>
+  owned?: boolean
+}
+
+function isErc721OwnershipPrecondition(precondition: any): precondition is Erc721OwnershipPrecondition {
+  return (
+    typeof precondition === 'object' &&
+    precondition.type === 'erc721-ownership' &&
+    ethers.isAddress(precondition.address) &&
+    ethers.isAddress(precondition.token) &&
+    isBigNumberish(precondition.tokenId) &&
+    (precondition.owned === undefined || typeof precondition.owned === 'boolean')
+  )
+}
</code_context>
<issue_to_address>
**issue (bug_risk):** Inconsistent null/undefined guard compared to other `is*Precondition` functions may cause runtime errors.

Other `is*Precondition` predicates (e.g. `isNativeBalancePrecondition`, `isErc20BalancePrecondition`) guard with `precondition && typeof precondition === 'object'`. Here, passing `null` still satisfies `typeof precondition === 'object'`, so `precondition.type` will throw. Please add a truthiness check (`precondition &&`) here and in other similar predicates like `isErc721ApprovalPrecondition` for consistency and to avoid runtime errors.
</issue_to_address>

### Comment 5
<location path="packages/relayer/src/precondition.ts" line_range="67-68" />
<code_context>
+function encodeNativeBalancePrecondition(precondition: NativeBalancePrecondition): proto.Precondition {
+  return {
+    type: precondition.type,
+    precondition: {
+      ...precondition,
+      type: undefined,
+      min: encodeBigNumberish(precondition.min),
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Spreading `precondition` and then setting `type: undefined` leaves an unnecessary `type` field in the encoded object.

Across multiple encoders (native/erc20/erc1155), `precondition: { ...precondition, type: undefined, ... }` leaves a `type` key with value `undefined` in the serialized proto, which can conflict with schema expectations. Consider destructuring to drop `type` entirely, e.g. `const { type, ...rest } = precondition;` and then using `precondition: { ...rest, ... }` so the field is removed rather than set to `undefined`.

Suggested implementation:

```typescript
function encodeNativeBalancePrecondition(precondition: NativeBalancePrecondition): proto.Precondition {
  const { type, ...rest } = precondition

  return {
    type,
    precondition: {
      ...rest,
      min: encodeBigNumberish(precondition.min),
      max: encodeBigNumberish(precondition.max)
    }
  }
}

```

You mentioned similar encoder patterns for ERC20 and ERC1155 preconditions. Apply the same destructuring approach in their respective encode functions:
1. Destructure `type` out of the precondition argument: `const { type, ...rest } = precondition`.
2. Use `type` for the top-level `type` field.
3. Use `rest` for the nested `precondition` object, instead of spreading the original object and setting `type: undefined`.
This will consistently avoid emitting `type: undefined` in all encoded preconditions.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread packages/services/api/src/index.ts
Comment thread packages/services/api/src/index.ts
Comment thread packages/services/api/src/index.ts
Comment thread packages/relayer/src/precondition.ts
Comment thread packages/relayer/src/precondition.ts
@vercel
vercel Bot temporarily deployed to Preview – sequence-js-web August 16, 2026 00:36 Inactive
@vercel
vercel Bot temporarily deployed to Preview – sequence-js-docs August 16, 2026 00:36 Inactive
@vercel
vercel Bot temporarily deployed to Preview – wagmi-project August 16, 2026 00:36 Inactive
@vercel
vercel Bot temporarily deployed to Preview – sequence.js August 16, 2026 00:36 Inactive
Implement SequenceBatchService for token approval and calls.

Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
@vercel
vercel Bot temporarily deployed to Preview – sequence-js-web August 16, 2026 09:26 Inactive
This file contains an example of using SequenceBatchBuilder to approve and transfer ERC20 tokens on the BSC network.

Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
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.

3 participants