Skip to main content

Signing and Identity

The SDK signs the unsigned DTO exactly as it will be posted to the Chain Gateway. Each signer has a default scheme, and two of them have an opt-in second one.

The signers and the signing primitives are exported by @gala-chain/gala-core-sdk (since 2.0.0; this package does not re-export them):

import { GSwap } from '@gala-chain/gswap-sdk';
import { BrowserWalletSigner, GalaWalletSigner, PrivateKeySigner } from '@gala-chain/gala-core-sdk';
SignerSignatureAccount/address input
PrivateKeySignerGalaChain native signature (signNative)Recovered from the private key
GalaWalletSigner on current walletsgala_signChainDto with native0x + 40 hex, eth| + 40 hex, client| + 24 hex, or the bare 24 hex
GalaWalletSigner { scheme: 'personal-sign' } (opt-in, needs a wallet with the fix)Personal-sign via gala_signChainDtoThe same account
BrowserWalletSignerEIP-1193 personal_sign with the SDK prefixSelected 0x + 40 hex Ethereum account
BrowserWalletSigner { scheme: 'eip712' } (opt-in)eth_signTypedData_v4 for the EIP-712-capable methodsSelected 0x + 40 hex Ethereum account; resolves a registered client| alias

Native signatures have no prefix, EIP-712 domain, or typed-data envelope. Personal-sign signatures cover the bare serialized DTO and send the EIP-191 header for it as the DTO's prefix; neither involves an EIP-712 domain.

BrowserWalletSigner defaults to personal_sign, which resolves the bare eth|<40 hex> identity. { scheme: 'eip712' } signs typed data instead, for the methods in EIP712_CAPABLE_METHODS (RequestTrade, AddLiquidity, RemoveLiquidity, CollectPositionFees), and so resolves a registered client| alias; CreatePool and any other method still use personal_sign in that mode. The domain chainId is read from the wallet with eth_chainId on every signature (a malformed answer is INVALID_CHAIN_ID). Use it only when the app must act as the client| identity of the connected account.

Native private-key signing​

import { GSwap } from '@gala-chain/gswap-sdk';
import { PrivateKeySigner } from '@gala-chain/gala-core-sdk';

const gSwap = new GSwap({
env: 'stage',
signer: new PrivateKeySigner(process.env.GALACHAIN_PRIVATE_KEY!),
walletAddress: '0x0123456789012345678901234567890123456789',
});

The native signature identifies the key to the chain. walletAddress, when provided, is the selected Ethereum account used for gateway attribution; the SDK does not add signerAddress or signerPublicKey hints to the DTO.

Gala Wallet version note​

Current Gala Wallet builds support the four-parameter call:

gala_signChainDto([serialize(dto), address, methodName, 'native'])

There is no automatic fallback: a wallet that rejects native surfaces its error. Passing { scheme: 'personal-sign' } explicitly uses the three-argument gala_signChainDto contract without the final native parameter: [serialize({...dto, prefix}), address, methodName], resolving the bare eth|<40 hex> identity. This requires a Gala Wallet build that signs the bare serialized DTO (the string without the prefix field; the wallet applies the EIP-191 header itself). Wallet builds that predate that fix hash the string with the prefix field still inside, so the signature recovers to an address nobody holds. Nothing in the SDK selects this scheme on its own.

new GalaWalletSigner(account, { selectAddress }) accepts the account as 0x + 40 hex, eth| + 40 hex (normalized to 0x...), client| + 24 hex, or the bare 24 hex a direct client| login keeps. selectAddress is the identity (client|... or eth|...) the wallet is switched to with window.gala.setAddress before each signature, when the wallet offers it. The wallet's 130-hex answer is passed through bare or 0x-prefixed; anything else is INVALID_SIGNATURE. A page without window.gala gets GALA_WALLET_NOT_AVAILABLE.

Browser wallets​

Pass an EIP-1193 provider and the selected 0x Ethereum account to BrowserWalletSigner. By default the signer requests personal_sign (see the eip712 option above) and sends { ...dto, prefix, signature } to the gateway. To use an ethers BrowserProvider as the provider, wrap it with eip1193ProviderFromEthers(provider) (also from @gala-chain/gala-core-sdk).

A wallet or app that holds the key itself signs with the core package's primitives (signNative, signChainDtoNative, signChainDtoPersonalSign, signTypedDataPayload, createLazyPrivateKeySigner); see "Signing primitives for wallets" in App and Wallet Integration. The primitives are pinned byte for byte to the Gala Wallet's signing code by golden-vector fixtures (the fixtures and their suite live in packages/gala-core-sdk/tests).

For v2 DEX operations, X-Wallet-Address is only an attribution hint; it does not cause a SIGNER_MISMATCH check because these operations have no signerField. SIGNER_MISMATCH applies to contract operations that explicitly name an actor. A mismatched signing scheme can still produce SIGNATURE_INVALID.