Skip to content

feat(dx): implement contract ABI codegen pipeline#580

Open
Marvy247 wants to merge 5 commits into
Epta-Node:mainfrom
Marvy247:main
Open

feat(dx): implement contract ABI codegen pipeline#580
Marvy247 wants to merge 5 commits into
Epta-Node:mainfrom
Marvy247:main

Conversation

@Marvy247

Copy link
Copy Markdown

Implements a contract ABI codegen pipeline that auto-generates TypeScript types, SDK client methods, and event parsers from compiled Soroban contract WASM.

Changes

Phase 1 — Codegen pipeline (packages/codegen/)

  • packages/codegen/generate.ts — extracts ABI via stellar contract inspect --output xdr-base64-array, parses it with @stellar/stellar-sdk v15, and generates three output files
  • packages/sdk/src/generated/types.ts — TypeScript interfaces for every contract type with Soroban-to-TS type mappings
  • packages/sdk/src/generated/client.ts — typed GeneratedLinkoraClient class with one method per contract function
  • packages/sdk/src/generated/events.ts — typed event interfaces and parseContractEvent parser
  • pnpm codegen script that builds WASM and runs the generator
  • pnpm codegen:check CI step that fails if generated files are out of sync

Phase 2 — Migration of existing SDK

  • packages/sdk/src/types.ts — re-exports generated types instead of manual definitions
  • packages/sdk/src/client.tsLinkoraClient extends GeneratedLinkoraClient, adding error handling and number↔bigint conversions
  • packages/sdk/src/index.ts — exports from generated modules

Phase 3 — Shared types package

  • packages/types/ — zero-dependency package re-exporting from packages/sdk/src/generated/types.ts
  • Ready for consumption by apps/web and apps/mobile

Closes #577

@devJaja devJaja self-requested a review June 19, 2026 14:33
@devJaja

devJaja commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Thanks for this @Marvy247 — the core pipeline is solid and addresses the root cause of the manual sync problem.
The generate.sh script should be cleaned up regardless, resolve the conflict, make sure all CI checks pass. Then its ready to be merge

- Add packages/codegen/ with generate.ts that extracts ABI from compiled
  WASM via stellar contract inspect and auto-generates TypeScript types,
  client methods, and event parsers
- Generate packages/sdk/src/generated/{types,client,events,index}.ts
- Update packages/sdk/src/types.ts to re-export generated types
- Refactor LinkoraClient to extend GeneratedLinkoraClient with
  error handling and type conversion layer
- Add pnpm codegen and pnpm codegen:check scripts
- Add codegen-check CI job to .github/workflows/ci.yml
- Create packages/types/ shared package for cross-app type consumption

Closes Epta-Node#577

@devJaja devJaja left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review: Request Changes ⚠️

Good architecture overall @Marvy247 — the XDR-based ABI extraction approach is correct and the CI check is well-wired. But there are two blocking bugs in the generated output that need to be fixed before this can merge.

Blocking
1. getFollowers and getFollowing are generated without offset and limit parameters.  The contract requires (user, offset: u32, limit: u32) for both functions. The generated client omits the pagination args entirely:

// Generated — WRONG
async getFollowers(user: string): Promise<string[]> {
const retval = await this.simulateCall("get_followers", scvAddress(user));

Calling these will fail at the Soroban level with an argument count mismatch. This is the exact desync this PR was built to prevent. The codegen needs to correctly emit all parameters for these functions.

  1. createPost is classified as a read method (simulate-only) when it's a mutating function.
    Because create_post returns a u64 (the new post ID), the codegen places it in readMethods and generates it as a simulateCall. Simulation never writes state — callers will get back a post ID but no post will actually be created on-chain. The codegen needs a way to classify functions that return values but are state-mutating. create_post must be in writeMethods, returning the signed XDR envelope.

  2. Governance UDTs are missing from generated/types.ts.
    GovParameter, GovConfig, GovProposal, and GovStatus are #[contracttype] structs/enums that appear in public function signatures but are absent from the generated types file. Any caller using governance functions would get any.

Non-blocking (fix in follow-up)

  • apps/web and apps/mobile still import types directly — neither was updated to consume @linkora/types. Please either update them in this PR or open a follow-up issue immediately.
  • packages/sdk/generate.sh is still present alongside the packages/codegen/ pipeline. Remove it or document what it's for.
  • scvAddressVec only handles string[]. Any Vec where T is not an address falls through to a bare nativeToScVal, which may produce incorrect ScVal encoding for future contract functions. Document the limitation.

@vercel

vercel Bot commented Jun 22, 2026

Copy link
Copy Markdown

@Marvy247 is attempting to deploy a commit to the Jaja's projects Team on Vercel.

A member of the Team first needs to authorize it.

@devJaja

devJaja commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Nice Implementation @Marvy247 , I can see the changes are now fully implemented.
but quick one , all CI checks are failing, fix it then the PR is ready to be merge

- Fix getFollowers/getFollowing missing offset/limit params (rebuild WASM)
- Fix createPost classified as read method (name-based read/write heuristic)
- Add governance UDTs (GovParameter, GovConfig, GovProposal, GovStatus) to types
- Fix UdtUnionV0 enum parsing in codegen
- Add missing type imports in generated client.ts and events.ts
- Remove packages/sdk/generate.sh
- Update apps/mobile to consume @linkora/types
- Update LinkoraClient wrapper for new generated methods
- Document scvAddressVec limitation
@devJaja

devJaja commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

@Marvy247 The CI checks are still failing

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

Labels

None yet

Projects

None yet

2 participants