Files
bridge/internal/txassembler
zeekay 4dfb24878c feat(txassembler): SOL message build + signature finalize
Adds SOLAssembler — companion to the EVM Assembler — that constructs
Solana transactions for the bridge's destination-release flow:

  - PreSign: fetch a recent blockhash via JSON-RPC getLatestBlockhash,
    build a v0 message (one signer = the MPC release wallet as fee
    payer, one recipient, lamport amount), serialize the bytes to be
    signed. SPL token mode (when SourceMint is set) derives source +
    destination ATAs via solana.FindAssociatedTokenAddress and probes
    the destination ATA via getAccountInfo — if absent, the assembler
    prepends a CreateAssociatedTokenAccount instruction so the release
    wallet pays the ~2_039_280 lamport rent + creates the account.
  - Finalize: slot the 64-byte Ed25519 signature into Transaction
    .Signatures[0], serialize the full wire tx with MarshalBinary, and
    base64-encode for JSON-RPC sendTransaction (encoding:base64). The
    signature itself doubles as the canonical Solana "tx hash" — return
    it base58-encoded for SDK consumption.

Dependency: github.com/gagliardetto/solana-go v1.20.0 — the de facto
standard Go client. The assembler stays decoupled from the broader
*rpc.Client beyond GetLatestBlockhash + GetAccountInfo, so the
broadcast layer can use its own JSON-RPC endpoint.

Helpers:
  - LamportsFromFloat(amount, decimals): safe float → uint64 conversion
    with overflow protection. 9dp for native SOL; varies for SPL.
  - ParseSOLSignatureHex(s): decodes a 128-char hex string to a fixed
    [64]byte buffer — used by the signing driver when the dashboard
    returns the Ed25519 sig in hex form.
  - SOLDefaultBlockhashURL(network): canonical RPC URL per network.

Tests (sol_test.go) cover:
  - Native transfer happy path: instruction is system.Transfer at
    Account[0] = payer; round-trip of MessageBytes through
    Message.Unmarshal yields an identical message.
  - SPL transfer with destination ATA missing: 2 instructions
    (ata.Create, then token.Transfer), destination ATA correctly
    derived and probed.
  - SPL transfer with destination ATA present: only 1 instruction.
  - Finalize round-trip: rawTx parses back through solana-go's
    Transaction decoder with matching signature + payer + blockhash.
  - Error paths: unknown network, zero amount, malformed payer addr.
  - ParseSOLSignatureHex + LamportsFromFloat: corner cases.

Total: 12 SOL tests, all green.
2026-05-27 17:45:02 -07:00
..
2026-05-27 14:49:55 +02:00
2026-05-28 00:10:03 +02:00