Skip to main content

gSwap for Uniswap Users

gSwap uses familiar concentrated-liquidity ideas, but its contract and transaction model are different from Uniswap V3.

ConceptUniswap V3gSwap SDK
Pool identityToken addresses plus feeRegistered trading symbols plus fee
Token inputERC-20 addressSymbol or GalaChain class key
AmountsRaw integer unitsHuman-readable decimal strings
QuoteQuoter contract callBackend offline quote engine
Write pathRouter transactionSigned DTO posted to the swap backend's chain-gateway route
ConfirmationTransaction receiptQueued swap acknowledgement, then SubmittedTransaction.confirm()
Position identityNFT tokenIdPool, owner, and tick range; no positionId in the SDK API
Fee tiersDeployment-specific0, 500, 3000, 10000

Quotes​

The examples on this page continue from a gSwap client built as in Getting started (stage environment, a signer for writes) and run in an ES module (top-level await).

Uniswap's quoteExactInputSingle is replaced by a read-only SDK method. An omitted fee compares every available v2 tier:

const quote = await gSwap.quoting.quoteExactInput('GWETH', 'GUSDC', '0.1');
console.log(quote.feeTier, quote.amountOut, quote.totalFees);

const exactOutput = await gSwap.quoting.quoteExactOutput('GWETH', 'GUSDC', '3000', 3000);

Swaps​

The v2 SDK accepts the same exact-input/exact-output intent, but the slippage fields are explicit and the signer is configured on the client:

import BigNumber from 'bignumber.js'; // a dependency of the SDK; install it in your own app too

// The slippage bound is the least you accept (here 1% under the quote), not the quote itself.
const tx = await gSwap.swaps.swap('GWETH', 'GUSDC', quote.feeTier, {
exactIn: '0.1',
amountOutMinimum: new BigNumber(quote.amountOut).multipliedBy('0.99').toFixed(),
});
console.log(tx.mode, tx.uniqueKey, tx.transactionId);
const applied = await tx.confirm();
console.log(applied.result);

The swap backend forwards the signed DTO to the chain gateway through /v1/chain/asset/dex-contract/RequestTrade. The acknowledgement is queued, so confirm() reads the applied outcome from apply-results. There is no router ABI or bundler, and confirming a swap needs no socket event subscription (gSwap.stream is optional realtime data). Persist tx.uniqueKey so an uncertain submit or confirmation can be checked again without resubmitting.

Liquidity​

Uniswap's NFT mint is a gSwap AddLiquidity write. The position is merged by pool, owner, and tick range, and an add operation supplies exactly one deposit side. A range that does not contain the pool's current tick takes only one token and earns no fees, so derive it from the pool's tick (60 is the spacing of fee 3000). Confirming a liquidity write needs walletAddress on the client:

const slot0 = await gSwap.pools.getSlot0('GUSDC', 'GWETH', 3000);
const tx = await gSwap.positions.addLiquidityByTicks({
token0: 'GUSDC',
token1: 'GWETH',
fee: 3000,
tickLower: Math.floor((slot0.tick - 6000) / 60) * 60,
tickUpper: Math.ceil((slot0.tick + 6000) / 60) * 60,
amount: '3000',
amountIsToken0: true,
});
await tx.confirm();

Use addLiquidityByPrice when a UI collects token1-per-token0 prices. The SDK converts prices to spacing-aligned ticks. Spacing is 200 for fee 0, 10 for 500, 60 for 3000, and 200 for 10000.

removeLiquidity takes an optional token withdrawal quantity. Omitting both quantities closes the position and sweeps fees. collectPositionFees always sweeps the complete accrued balance; there is no partial collect amount.

Identity and signing​

Uniswap users often think in terms of an EVM address. GalaChain has two alias families: native keys resolve registered client|<24-hex> identities, while personal-sign browser wallets resolve bare eth|<40-hex> identities. The signers come from @gala-chain/gala-core-sdk. PrivateKeySigner is native, GalaWalletSigner is native (personal-sign is opt-in and needs a wallet build with the phantom-signer fix), and BrowserWalletSigner uses EIP-1193 personal-sign by default (an opt-in { scheme: 'eip712' } signs typed data, which also resolves a registered client| alias). Nothing else in v2 uses EIP-712.

See Signing and Identity and Migration from 0.x for the complete mapping.