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';
| Signer | Signature | Account/address input |
|---|---|---|
PrivateKeySigner | GalaChain native signature (signNative) | Recovered from the private key |
GalaWalletSigner on current wallets | gala_signChainDto with native | 0x + 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_signChainDto | The same account |
BrowserWalletSigner | EIP-1193 personal_sign with the SDK prefix | Selected 0x + 40 hex Ethereum account |
BrowserWalletSigner { scheme: 'eip712' } (opt-in) | eth_signTypedData_v4 for the EIP-712-capable methods | Selected 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.