Skip to content

feat: support Solana standard orders#3

Merged
Asem-Abdelhady merged 16 commits intomainfrom
asem/V2-109/solana-orders
Apr 6, 2026
Merged

feat: support Solana standard orders#3
Asem-Abdelhady merged 16 commits intomainfrom
asem/V2-109/solana-orders

Conversation

@Asem-Abdelhady
Copy link
Copy Markdown
Contributor

@Asem-Abdelhady Asem-Abdelhady commented Mar 9, 2026

Summary

  • Adds StandardSolana order type — a single-input variant of StandardOrder for Solana input settlers
  • Adds Borsh serialization (borshEncodeSolanaOrder) and order ID derivation (computeStandardSolanaId) matching the common::types::StandardOrder layout in catalyst-intent-svm
  • Routes EVM→Solana output tokens to the correct output settler PDA in buildMandateOutputs, falling back to COIN_FILLER for EVM outputs
  • Adds outputRecipient option to CreateIntentOptions to support a different recipient than the connected wallet
  • Extends CoreToken with chainNameSpace: "eip155" | "solana" (CAIP namespace) for output routing

Design notes

  • StandardSolana enforces a single input — the Solana program only supports one SPL token input per order. standardOrderToSolanaOrder throws if called with zero or more than one input.
  • Input amount is encoded as u64 (Solana stores SPL amounts as u64); output amount is bytes32 to match the EVM ABI layout.
  • Mainnet and testnet settler addresses are undefined with TODO comments — inputSettlerForSolana and buildMandateOutputs throw for undeployed chains.

Testing

  • src/intent/solanaStandard.spec.ts — full coverage: Borsh encoding golden value, u32 overflow guards, mutation tests, conversion helpers, StandardSolanaIntent class
  • src/intent/helpers/output-encoding.spec.ts — Solana PDA routing, unsupported chain rejection, EVM regression coverage
  • src/intent/helpers/shared.spec.tsinputSettlerForSolana happy path and error paths
  • Run all tests: bun test

@Asem-Abdelhady Asem-Abdelhady requested a review from reednaa March 9, 2026 21:55
Copy link
Copy Markdown
Member

@reednaa reednaa left a comment

Choose a reason for hiding this comment

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

A few nits. Ideally we simplify the library rather than add to it.

Comment thread src/deps.ts Outdated
Comment thread src/types/solana.ts Outdated
Comment thread src/intent/solana.ts Outdated
Comment thread src/deps.ts Outdated
Comment thread src/deps.ts Outdated
Comment thread src/deps.ts Outdated
@Asem-Abdelhady Asem-Abdelhady requested a review from reednaa March 11, 2026 10:17
Copy link
Copy Markdown
Member

@reednaa reednaa left a comment

Choose a reason for hiding this comment

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

The added files does not have test coverage unlike all other files in this repository.

Provide coverage of solanaStandard.spec.ts.

Here are a variety of agent findings:

src/intent/solanaStandard.ts

  • The amount field in mandateInputSchema uses "u64" but borshEncodeSolanaOrder passes BigInt(order.input.amount) — this is fine for
    u64, but the amount in mandateOutputSchema uses bytes32 (big-endian 32-byte encoding), which is inconsistent. Verify this matches
    the SVM program's actual layout.
  • The standardOrderToSolanaOrder conversion only uses the first input (order.inputs[0]), silently dropping all others. A
    StandardOrder can have multiple inputs — should this throw if inputs.length > 1 rather than silently truncating?
  • borshEncodeSolanaOrder is exported but not re-exported from src/intent/index.ts. Intentional or oversight?

src/intent/helpers/output-encoding.ts

  • outputSettler is now computed per-output via getSettler?.(token.chainId) ?? COIN_FILLER — this is a meaningful behavioral change
    for all EVM orders too (previously settled globally). Ensure no regression for existing EVM paths.

src/helpers/convert.ts

  • The early-return guard for already-bytes32 addresses is reasonable, but a Solana address (base58 string) would fail silently or
    produce wrong output if passed here. The comment says "Accept only EVM addresses here" but there's no enforcement — could confuse
    callers

Comment thread src/helpers/convert.ts Outdated

export function addressToBytes32(address: `0x${string}`): `0x${string}` {
if (address.length === 66) return address; // already bytes32 with 0x prefix
if (address.length === 64) return `0x${address}`; // already bytes32 without 0x
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this properly catch 64 length addresses prefixed with 0x?

I would rather use something like: 0x${address.replace("0x", "").padStart("0", 64)}

Copy link
Copy Markdown
Contributor Author

@Asem-Abdelhady Asem-Abdelhady Mar 13, 2026

Choose a reason for hiding this comment

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

yeah i think we should remove if (address.length === 64) also we don't need to check the address length in address.length !== 40 for EVM since we are already constraining the template with address: 0x${string} in the parameters.

Comment thread src/intent/helpers/output-encoding.ts Outdated
Comment thread src/intent/helpers/shared.ts Outdated
Comment thread src/intent/create.ts Outdated
Comment thread src/intent/create.ts Outdated
Comment thread src/intent/types.ts
asOrder(): TOrder;
inputChains(): bigint[];
orderId(): `0x${string}`;
compactClaimHash(): `0x${string}`;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is required. Add a handler for EVM vs Solana and then provide compactClaimHash if chain is identified as EVM.

Comment thread src/intent/create.ts Outdated
Comment thread src/intent/helpers/output-encoding.ts Outdated
Comment thread src/intent/fromOrder.ts Outdated
Asem-Abdelhady and others added 7 commits March 16, 2026 21:58
The PR accidentally swapped compact↔escrow settler assignments. Restores
the original: compact/single→COMPACT_LIFI, compact/multi→MULTICHAIN_COMPACT,
escrow/single→ESCROW_LIFI, escrow/multi→MULTICHAIN_ESCROW.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Asem-Abdelhady Asem-Abdelhady requested a review from reednaa April 1, 2026 12:57
Comment thread src/types/token.ts Outdated
Comment thread src/constants.ts
Comment on lines +22 to +24
export const SOLANA_MAINNET_CHAIN_ID = 1151111081099710n;
export const SOLANA_TESTNET_CHAIN_ID = 1151111081099711n;
export const SOLANA_DEVNET_CHAIN_ID = 1151111081099712n;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we want to consider renaming these to just SOLANA_MAINNET, SOLANA_TESTNET, etc?

Comment thread src/types/order.ts Outdated
@Asem-Abdelhady Asem-Abdelhady changed the title Asem/v2 109/solana orders feat: support Solana standard orders Apr 2, 2026
@Asem-Abdelhady Asem-Abdelhady requested a review from reednaa April 3, 2026 11:56
Comment thread src/types/order.ts
export type StandardSolana = {
user: `0x${string}`;
nonce: bigint;
originChainId: bigint;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
originChainId: bigint;
originChainId: SOLANA_MAINNET_CHAIN_ID I SOLANA_TESTNET_CHAIN_ID | SOLANA_DEVNET_CHAIN_ID;

Comment thread src/intent/standard.ts
inputSettler: `0x${string}`;
private readonly order: StandardOrder;
private readonly order: StandardEVM;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

chainNamespace: ""

Comment thread src/intent/standard.ts

orderId(): `0x${string}` {
return computeStandardOrderId(this.inputSettler, this.order);
return computeStandardEVMId(this.inputSettler, this.order);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Fix name

Comment thread src/intent/standard.ts
@@ -60,7 +60,7 @@ export class StandardOrderIntent implements OrderIntentCommon<StandardOrder> {
}

orderId(): `0x${string}` {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

if (namespace == "EIP155") EVMIntent.orderId()...
if (namespace == "solana") SolanaIntent.orderId()

Comment thread src/intent/standard.ts
return computeStandardEVMId(this.inputSettler, this.order);
}

compactClaimHash(): `0x${string}` {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
compactClaimHash(): `0x${string}` {
compactClaimHash(this: StandardOrder<"EIP155">): `0x${string}` {

@Asem-Abdelhady
Copy link
Copy Markdown
Contributor Author

After discussing it with @reednaa this PR will be merged to finalise lintent.org.
New branch should be made to do changes of:

1- Remove: CHAIN_ID from solana chain ids constants names.
2- Change the standard orders and intents strutucure to be generic bounded structure with namespace instead of making it separate interfaces.
3- Rename/fix: functions names to reflect the new changes.

@Asem-Abdelhady Asem-Abdelhady merged commit aab6585 into main Apr 6, 2026
1 check passed
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