Skip to content

Comments

feat: add chain modules#726

Open
yilmazbahadir wants to merge 15 commits intodevfrom
baha/feat/asset-modules
Open

feat: add chain modules#726
yilmazbahadir wants to merge 15 commits intodevfrom
baha/feat/asset-modules

Conversation

@yilmazbahadir
Copy link
Collaborator

@yilmazbahadir yilmazbahadir commented Feb 10, 2026

📝 Summary

  • Refactors SDK chain handling to a plugin registry model so chain-specific signer logic is no longer hardcoded in @gridplus/sdk.
  • Moves Lattice signer implementations into each chain package (btc, evm, solana, cosmos) and exports latticePlugin from each package.
  • Adds a static built-in chain manifest plus a single discovery path for all runtimes (no Node-only scan path).
  • Keeps consumer experience simple: defaults auto-register in setup(); optional custom plugins can be passed via setup({ chainPlugins }).

🔧 Context / Implementation

  • Added registry primitives in @gridplus/chain-core (DeviceId, ChainPlugin, createChainRegistry, resolver helpers).
  • Replaced SDK-side monolithic signer module with:
    • packages/sdk/src/chains/registry.ts
    • packages/sdk/src/chains/context.ts
    • packages/sdk/src/chains/discovery.ts
    • packages/sdk/src/chains/defaultManifest.ts
  • Updated setup() to support:
    • autoRegisterChains (default true)
    • defaultDevice (default 'lattice')
    • chainPlugins (validated; duplicate-in-input throws; built-in key can be overridden)
  • Updated signing/address APIs to use useChain(...) runtime resolution with lazy signer/adapter creation and cache invalidation.

🧪 Test Plan

  1. cd packages/sdk && npm run typecheck
  2. cd packages/sdk && npm run test-unit
  3. Verify behavior:
    • setup() auto-registers built-ins (btc, evm, solana, cosmos) by default.
    • setup({ autoRegisterChains: false, chainPlugins: [...] }) registers only provided plugins.
    • setup({ chainPlugins }) can override a built-in (chainId, device) key.
    • Existing signing/address helpers still work through the new registry path.

Expected result: all checks pass and runtime behavior matches previous helper APIs while using plugin-based chain resolution.

🖼️ Screenshots (if applicable)

Before After
N/A (backend/architecture refactor) N/A

Chain Registry Architecture (SDK + Chain Packages)

1) Component View

flowchart LR
    App["Consumer App"] --> Setup["setup(...)"]
    App --> Helpers["api/signing.ts\napi/addresses.ts"]

    subgraph SDK["@gridplus/sdk"]
      Setup --> RuntimeCfg["configureChainRuntime(...)"]
      Setup --> DiscoverCall["discoverAndRegisterChains({force:true})"]
      Setup --> CustomReg["registerConfiguredChainPlugins(...)"]
      Helpers --> UseChain["useChain(chainId, options)"]
      UseChain --> Registry["chains/registry.ts"]
      Registry --> Ctx["createDeviceContext()"]
      Ctx --> Runtime["queue/getClient/constants/services"]
      DiscoverCall --> Discovery["chains/discovery.ts"]
      Discovery --> Manifest["chains/defaultManifest.ts"]
    end

    subgraph Core["@gridplus/chain-core"]
      CoreRegistry["createChainRegistry()\nChainPlugin + DeviceId + resolve()"]
    end

    subgraph Chains["@gridplus/{btc,evm,solana,cosmos}"]
      Btc["btc/src/devices/lattice.ts\nlatticePlugin"]
      Evm["evm/src/devices/lattice.ts\nlatticePlugin"]
      Sol["solana/src/devices/lattice.ts\nlatticePlugin"]
      Cos["cosmos/src/devices/lattice.ts\nlatticePlugin"]
      Cadix["future: */src/devices/cadix.ts\ncadixPlugin"]
    end

    Registry --> CoreRegistry
    Manifest --> Btc
    Manifest --> Evm
    Manifest --> Sol
    Manifest --> Cos
    CustomReg --> Cadix

    Registry --> Plugin["resolved plugin (chainId:device)"]
    Plugin --> Signer["createSigner(context)"]
    Signer --> Adapter["module.create(...) or createAdapter(...)"]
    Adapter --> Device["Client calls via queue(...)"]
Loading

2) Runtime Flow (Setup + Use)

sequenceDiagram
    participant App
    participant Setup as setup()
    participant Registry as chains/registry.ts
    participant Discovery as chains/discovery.ts
    participant Manifest as defaultManifest.ts
    participant API as signing/addresses helpers
    participant Plugin as ChainPlugin
    participant Device as Client

    App->>Setup: setup({autoRegisterChains, defaultDevice, chainPlugins})
    Setup->>Registry: configureChainRuntime(..., resetCache=true)

    alt autoRegisterChains != false
      Setup->>Registry: discoverAndRegisterChains({force:true})
      Registry->>Discovery: discover(registerFn)
      Discovery->>Manifest: iterate DEFAULT_CHAIN_PLUGINS
      loop each default plugin
        Discovery->>Registry: register if missing
      end
    end

    opt chainPlugins provided
      Setup->>Registry: unregisterChain(key) if existing
      Setup->>Registry: registerChainPlugin(plugin) // override
    end

    App->>API: sign*/fetch* request
    API->>Registry: useChain(chainId, {device?, adapterOptions?})
    Registry->>Registry: resolve(chainId, device/defaultDevice)

    alt cache miss or generation changed
      Registry->>Plugin: createSigner(createDeviceContext())
      Plugin-->>Registry: signer
      Registry->>Plugin: createAdapter(...) or module.create(...)
      Plugin-->>Registry: adapter
    else cache hit
      Registry-->>Registry: reuse signer + adapter
    end

    Registry-->>API: adapter
    API->>Device: queue(client => sign/getAddresses/...)
    Device-->>API: result
Loading

3) Registry + Cache Lifecycle

stateDiagram-v2
    [*] --> RuntimeConfigured: configureChainRuntime()

    RuntimeConfigured --> BuiltInsRegistered: discoverAndRegisterChains()\n(autoRegisterChains=true)
    RuntimeConfigured --> RuntimeConfigured: discoverAndRegisterChains()\n(autoRegisterChains=false)

    BuiltInsRegistered --> BuiltInsRegistered: discoverAndRegisterChains()\n(idempotent)
    BuiltInsRegistered --> Overridden: setup({chainPlugins}) override

    Overridden --> Overridden: useChain() cache hit
    Overridden --> CacheRebuilt: useChain() cache miss
    CacheRebuilt --> Overridden: adapter memoized

    Overridden --> RuntimeConfigured: invalidateChainCache()\nunregisterChain()\nsetup(resetCache=true)
    RuntimeConfigured --> [*]
Loading

4) Behavior Matrix

Scenario Behavior
autoRegisterChains: true Built-in manifest plugins are registered during setup().
autoRegisterChains: false Built-ins are skipped; only explicit plugins exist.
Custom chainPlugins collides with built-in key Existing key is unregistered, then custom plugin is registered (override).
Duplicate keys inside chainPlugins input setup() throws.
Discovery registration failure for one default plugin Warning logged; discovery continues with remaining plugins.
useChain unresolved chain/device Throws with available device list for that chain (if any).

5) Source Map

  • packages/sdk/src/api/setup.ts
  • packages/sdk/src/api/signing.ts
  • packages/sdk/src/api/addresses.ts
  • packages/sdk/src/chains/registry.ts
  • packages/sdk/src/chains/discovery.ts
  • packages/sdk/src/chains/defaultManifest.ts
  • packages/sdk/src/chains/context.ts
  • packages/chains/chain-core/src/index.ts
  • packages/chains/btc/src/devices/lattice.ts
  • packages/chains/evm/src/devices/lattice.ts
  • packages/chains/solana/src/devices/lattice.ts
  • packages/chains/cosmos/src/devices/lattice.ts

@yilmazbahadir yilmazbahadir changed the title Baha/feat/asset modules feat: add asset modules Feb 10, 2026
…very

- add asset-core registry/plugin primitives (DeviceId, AssetPlugin, createAssetRegistry)
- move lattice signer implementations into each asset package and export `latticePlugin`
- add SDK static default manifest + single discovery path for built-in assets
- replace `sdk/src/assets/lattice.ts` with runtime registry/context/discovery modules
- wire `setup()` for `autoRegisterAssets`, `defaultDevice`, and `assetPlugins` overrides
- route signing/address helpers through `useAsset()` adapters with cache invalidation
- add unit tests for registry, discovery, default manifest, and setup plugin behavior
@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 20, 2026

Open in StackBlitz

npm i https://pkg.pr.new/GridPlus/gridplus-sdk@726

commit: b184fe8

Replace truthy checks with numeric validation in lattice device context guards for
`cosmos`, `evm`, and `solana` assets.

This prevents valid enum values like `0` (for example `HASHES.NONE` /
`CURVES.SECP256K1`) from being treated as missing and throwing false
"requires EXTERNAL constants" runtime errors.
@yilmazbahadir yilmazbahadir changed the title feat: add asset modules feat: add chain modules Feb 20, 2026
@yilmazbahadir yilmazbahadir force-pushed the baha/feat/asset-modules branch from 6053437 to b184fe8 Compare February 20, 2026 22:01
@yilmazbahadir yilmazbahadir marked this pull request as ready for review February 20, 2026 22:09
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b184fe8dbc

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

params: BtcGetAddressParams = {},
): Promise<Address> => {
const path = resolvePath(params, options);
return signer.getAddress(path, { format: params.format });

Choose a reason for hiding this comment

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

P2 Badge Apply resolved BTC format in single-address lookup

getAddress forwards only params.format, so adapter-level defaults (options.format) and the module’s own format resolution are skipped for single-address calls. In practice, getAddress()/getAccount() can ignore the configured BTC format while getAddresses() honors it, leading to inconsistent address type selection for the same adapter configuration.

Useful? React with 👍 / 👎.

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.

1 participant