feat(dx): implement contract ABI codegen pipeline#580
Conversation
|
Thanks for this @Marvy247 — the core pipeline is solid and addresses the root cause of the manual sync problem. |
- 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
left a comment
There was a problem hiding this comment.
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.
-
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. -
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.
|
@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. |
|
Nice Implementation @Marvy247 , I can see the changes are now fully implemented. |
- 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
|
@Marvy247 The CI checks are still failing |
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 viastellar contract inspect --output xdr-base64-array, parses it with@stellar/stellar-sdkv15, and generates three output filespackages/sdk/src/generated/types.ts— TypeScript interfaces for every contract type with Soroban-to-TS type mappingspackages/sdk/src/generated/client.ts— typedGeneratedLinkoraClientclass with one method per contract functionpackages/sdk/src/generated/events.ts— typed event interfaces andparseContractEventparserpnpm codegenscript that builds WASM and runs the generatorpnpm codegen:checkCI step that fails if generated files are out of syncPhase 2 — Migration of existing SDK
packages/sdk/src/types.ts— re-exports generated types instead of manual definitionspackages/sdk/src/client.ts—LinkoraClientextendsGeneratedLinkoraClient, adding error handling and number↔bigint conversionspackages/sdk/src/index.ts— exports from generated modulesPhase 3 — Shared types package
packages/types/— zero-dependency package re-exporting frompackages/sdk/src/generated/types.tsapps/webandapps/mobileCloses #577