@gala-chain/gala-core-sdk

中文文档
1.2.1发布于 2026/11/10Apache-2.0TypeScriptESM + CJS近 30 天下载 4762

The GalaChain core SDK: signing (native, personal-sign, EIP-712), the gateway transport, the gateway token reads (balances, token classes, NFT collections) and writes (transfer, burn, lock, unlock) and the shared error model, for every product SDK and app

原始使用文档
文档目录16 节
  1. Install
  2. Quick start
  3. What is in it
  4. Subpaths
  5. Bridge
  6. Wallet providers
  7. React
  8. Gateway writes
  9. NFT writes
  10. Gateway reads
  11. Signing parity
  12. React Native
  13. Bundle size
  14. Status
  15. Migrating from gswap-sdk 1.x
  16. License

GalaChain core SDK

Signing your own DTOs? Every signed write now needs dtoOperation. Per-endpoint mapping, before and after payloads and the errors: MIGRATING-TO-DTO-OPERATION.md. Using an SDK signer? Upgrade; it sets the field for you.

@gala-chain/gala-core-sdk is the layer every GalaChain product SDK and app shares: signing (native, personal-sign, EIP-712 and arbitrary typed data), the signers (private key, lazy private key, Gala Wallet, EIP-1193 browser wallets), the gateway transport (fetch requestor with timeouts, wire options, axios and ethers adapters), the gateway token reads (balances and holds, token classes, NFT collection authorizations) and writes (transfer, burn, lock, unlock), token class keys and write uniqueKeys, and the shared error model (GalaSDKError, its catalog, the failure view). It speaks to the GalaChain gateway generically; product backends (the DEX and Launchpad backends) have their own SDKs (@gala-chain/gswap-sdk, @gala-chain/launchpad-sdk) that build on it.

Install

npm install @gala-chain/gala-core-sdk

Pin the exact version in an app build. A product SDK takes core as a peer dependency: install it next to the product SDK, once.

Quick start

import { PrivateKeySigner, serialize, signNative, normalizePrivateKey, withDtoOperation } from '@gala-chain/gala-core-sdk';

const signer = new PrivateKeySigner(process.env.GALACHAIN_PRIVATE_KEY!);
// The chain refuses a signed DTO without the `dtoOperation` of the call it is sent to, and the field is
// part of what is signed: set it BEFORE signing (GatewayWrites and the product SDKs already do).
const dto = withDtoOperation('asset/token-contract', 'TransferToken', { quantity: '1', uniqueKey: 'k-1' });
const signed = await signer.signObject('TransferToken', dto);

// The primitives the signer is built on, byte-identical to @gala-chain/api:
const key = normalizePrivateKey(process.env.GALACHAIN_PRIVATE_KEY!);
console.log(serialize({ b: 1, a: 2 }), signNative(key, { a: 1 }));
key.fill(0);

What is in it

AreaExports
SignersPrivateKeySigner, createLazyPrivateKeySigner, GalaWalletSigner, BrowserWalletSigner, signPreSend, signPreSendFor, type GalaChainSigner
Signingserialize, getPayloadToSign, signNative, signPersonalMessage, personalSignPrefixFor, fixpointPrefixFor, signChainDto*, signRawObject, generateEIP712Types, buildEIP712Payload, hashTypedData, signTypedDataPayload; the signed dtoOperation: withDtoOperation, dtoOperationOf, CHAIN_CONTRACT_OPERATION_PREFIXES, type ChainContractPath
TransportfetchRequestor, requestWithTimeout (kind: { write: false } makes a read's timeout and transport failure say write: false), buildRequestHeaders, buildQueryString, readRetryAfter, httpRequestorFromAxios, eip1193ProviderFromEthers, isFetchTransportFailure, types HttpRequestor, WireOptions, RequestKind
Gateway readsGatewayReads (fetchBalances, fetchTokenBalance, fetchNftBalances, fetchTokenClasses, fetchTokenClassesWithSupply, fetchTokenClass, fetchTokenDetails, fetchTokenClassesPage, fetchAllTokenClasses, fetchNftCollectionAuthorizationsPage, fetchAllNftCollectionAuthorizations, fetchPublicKey), GATEWAY_READ_METHODS, GATEWAY_READ_LIMITS, types GalaChainTokenBalance, GalaChainTokenBalanceSummary, GalaChainTokenClass, GalaChainTokenDetails, GalaChainPage, GalaChainPublicKey
Gateway writesGatewayWrites (transferGala, transferToken, burnTokens, lockTokens, unlockTokens; NFTs: claimNftCollection, createNftCollection, mintNft, estimateNftFee), galaChainUserRef (a user reference in the one spelling the gateway accepts), GATEWAY_WRITE_METHODS, GATEWAY_WRITE_BATCH_LIMITS, GALA_TOKEN_CLASS_KEY, NFT_WRITE_METHODS, NFT_MINT_LIMIT, types GatewayWritesOptions, GatewayWriteReceipt, WriteReceipt, TokenNameResolver, TokenQuantityInput, NftFeeRequest, NftFeeQuote, ClaimNftCollectionInput, CreateNftCollectionInput, MintNftInput
DeploymentsGALA_CHAIN_ENVIRONMENTS (gateway and DEX API of prod / stage)
KeyscompositeKeyOf, tryParseTokenClassKey, tryParseCompositeKey, createUniqueKey, assertUniqueKey, isValidUniqueKey
WalletscreateWallet (random, from a private key, or from a 12/24-word mnemonic at m/44'/60'/0'/0/0), validateWalletInput, getPublicKeyFromPrivateKey, getEthereumAddressFromPrivateKey, checksumEthereumAddress, types GeneratedWallet, PublicKeyResult
ErrorsGalaSDKError, isGalaError, GALA_ERROR_CATALOG, galaErrorTemplates, GALA_ERROR_PHASE_BY_CODE, toFailureView, isWriteView, FAILURE_OUTCOMES
Wallet helpers (./wallet)isWalletUserRejection, walletDeclineCode, isGalaErrorLike
Wallet providers (./providers)PrivateKeyProvider, ExternalWalletProvider, GalaWalletProvider, detectWallets, subscribeToWalletChanges, getWalletByRdns, isWalletAvailable, findMetaMaskWallet, getMetaMaskWallet, findTrustWallet, getTrustWallet, hasAnyWallet, getInjectedEip1193Provider, KNOWN_WALLET_RDNS, createWalletProvider, createProviderFromEip1193, ensureConnected, getPrivateKeyIfAvailable, isPrivateKeyProvider, isExternalProvider, isEip1193Provider, type WalletProvider
React (./react)WalletProvider (context component), WalletContext, useWallet, useWalletContext, useWalletConnection, useWalletDetection, useWalletAddress, useGalaAddress, useWalletProvider, useIsWalletConnected
Bridge (./bridge)BridgeService (bridge out to and in from Ethereum and Solana, fees, status, external balances), EthereumBridgeStrategy, SolanaBridgeStrategy, BaseBridgeStrategy, GalaConnectClient, BridgeableTokenService, WrappableTokenService, WrapService (channel wrap / unwrap), createSolanaWallet, buildBridgeOutPayload (the signed bridge-out request), the bridge constants and token tables, the bridge types, RateLimiter, the token amount helpers (toBaseUnits, fromBaseUnits, formatTokenAmount, compareAmounts)

Subpaths

Each subpath is its own build: it loads the root (and ./react the providers) through the package, never a copy, so an app has one GalaSDKError class, one signer set and one set of provider classes (checked on the packed tarball by pnpm run check:pack, and on the source by tests/subpath_isolation.test.ts). The root never loads a subpath.

EntryWhat it is forLoads (besides the root)Peer it needs
@gala-chain/gala-core-sdkSigning, signers, transport, gateway reads and writes, keys, wallets, errors@noble/*, @scure/bip32, @scure/bip39, bignumber.jsnone
@gala-chain/gala-core-sdk/walletThe dependency-free wallet helpers (an app shell)nothing (not even the root)none
@gala-chain/gala-core-sdk/providersOne WalletProvider per wallet kind, EIP-6963 detection@noble/hashesnone
@gala-chain/gala-core-sdk/reactThe wallet context and hooks./providersreact (optional peer, 16.8 to 19; react-dom is not needed)
@gala-chain/gala-core-sdk/bridgeBridging GalaChain to and from Ethereum and Solana, channel wrap / unwrap, the bridgeable and wrappable token listsethers, @solana/web3.js, @solana/spl-token, @scure/base, bignumber.jsethers 6, @solana/web3.js 1.99+, @solana/spl-token 0.4.15+ (optional peers: install them when you import ./bridge)

Only ./bridge loads ethers or @solana/*: the root and the other subpaths never do (checked on the source by pnpm run check:rn-safety and the isolation test, and on the built files by the packed smoke).

Bridge

import { BridgeableTokenService, BridgeService, GalaConnectClient } from '@gala-chain/gala-core-sdk/bridge';

const walletAddress = 'eth|...';
// The DEX API's bridgeable token list (production by default; `baseUrl` for another deployment)
const tokens = new BridgeableTokenService(new GalaConnectClient({ walletAddress }));
const bridge = new BridgeService({
  environment: 'prod', // or 'stage': GalaConnect, the gateway and the RPCs of that deployment
  galaChainWalletAddress: walletAddress,
  ethereumPrivateKey: process.env.ETH_PRIVATE_KEY!, // signs the bridge-out request and Ethereum deposits
  bridgeableTokenService: tokens, // resolves a token id to its bridge symbol
});
// Token ids are class keys (pipe form or object): a bare symbol is refused (symbols are not unique)
const GALA = 'GALA|Unit|none|none';
const fee = await bridge.estimateBridgeFee({ tokenId: GALA, destinationChain: 'Ethereum' });
const out = await bridge.bridgeOut({ tokenId: GALA, amount: '10', destinationChain: 'Ethereum', recipientAddress: '0x...' });
const status = await bridge.waitForBridgeCompletion(out.transactionHash);

A bridge or wrap that does not complete throws a GalaSDKError (never a "failed" result). Once a bridge-out request was accepted the tokens may be locked: a later failure is BRIDGE_OUT_OUTCOME_UNKNOWN (with the step, the bridge request id and the uniqueKey), and a deposit that may have been sent is BRIDGE_DEPOSIT_OUTCOME_UNKNOWN; neither is ever retried by the SDK. WrapService wraps a token from its own channel to the asset channel (MUSIC to GMUSIC) and back, signed natively by a GalaChainSigner; createWrapService({ environment, walletAddress, signer }) builds one for prod or stage (the environment supplies the GalaConnect, swap backend and gateway URLs; an option overrides any), so a wrap needs no product SDK. A RequestTokenBridgeOut (the bridge-out and the wrap / unwrap) signs the TOKEN contract's dtoOperation (asset-channel_basic-asset_GalaChainToken:RequestTokenBridgeOut, not the bridge contract's, which the chain refuses; verified on stage, 2026-11-02) as a field of its EIP-712 GalaTransaction type, so the signature covers it; buildBridgeOutPayload does this. The wrap / unwrap request carries no wrap field: the chain's strict validation refuses it and the direction is the destination channel id (verified on stage in both directions). It is signed under the SOURCE channel's token contract (asset-channel_basic-asset_GalaChainToken:RequestTokenBridgeOut to unwrap, music_music_GalaChainToken:RequestTokenBridgeOut to wrap; the gateway answers a wrong operation with a bare 401 UNAUTHORIZED) and goes through the swap backend's chain route (GalaConnectClient.requestWrapOut, which needs the client's dexBackendBaseUrl: the backend root without /api/v1; it checks the signer, the amount and the operation, then relays to the chain), not through GalaConnect's /RequestTokenBridgeOut, which only treats a request as a wrap when it carries the wrap: true the chain refuses. Only the completion (BridgeTokenOut) is GalaConnect's: the chain wants the bridge authority's signature for it (a user-signed one is refused with NOT_A_BRIDGE_AUTHORITY). The other bridge strings, all seen live on stage and signed by GalaConnect (this SDK signs none of them): BridgeTokenOut on /asset/bridge-contract is asset-channel_bridge-chaincode_BridgeContract:BridgeTokenOut (the operation table's bridge-contract entry is right for it), and the grants embedded in a BridgeTokenOut sign asset-channel_bridge-chaincode_GalaChainToken:GrantAllowance, which is NOT in the platform's operation table.

TypeScript: the ./bridge declarations name @solana/web3.js types, whose own declarations import Node's http and https, so a TypeScript app that imports ./bridge has @types/node (with TypeScript 6, "types": ["node"]) or skipLibCheck. The other entries need no Node types.

Wallet providers

The Gala Wallet browser extension (install, what it signs, its provider methods) has its own page: docs/wallet-extension.md.

import { detectWallets, ExternalWalletProvider, PrivateKeyProvider } from '@gala-chain/gala-core-sdk/providers';

const { wallets } = await detectWallets();            // EIP-6963 announcements, then window.ethereum / window.gala
const first = wallets[0];
if (first === undefined) throw new Error('No wallet announced itself');
const provider = new ExternalWalletProvider(first.provider);
await provider.connect();
await provider.signMessage('Hello');                   // personal_sign
const signer = provider.getSigner();                  // a GalaChainSigner for GatewayWrites, gswap-sdk, ...

const server = new PrivateKeyProvider(process.env.GALACHAIN_PRIVATE_KEY!); // Node, CLI, bots

A provider listens to its wallet only while connected, follows accountsChanged (an empty or malformed account list disconnects it), and reads its connection once per operation, so one operation never names two accounts. getSigner() is bound to the account connected when it is called: after an account change, get a new signer. GalaWalletProvider selects its account in the extension before each signature, serialized with every other signer of the same extension. Every failure is a GalaSDKError: WALLET_CONNECTION_FAILED (user_rejected, no_accounts, failed), WALLET_NOT_CONNECTED, SIGNING_FAILED (user_rejected when the person declined), INVALID_SIGNATURE, PRIVATE_KEY_NOT_ACCESSIBLE, INVALID_WALLET_PROVIDER_CONFIG. Detection works without a window (Node, SSR, React Native): it finds nothing and throws nothing.

React

import { WalletProvider, useWalletConnection, useWalletDetection, useWallet } from '@gala-chain/gala-core-sdk/react';

<WalletProvider autoDetect>
  <App />
</WalletProvider>;

const { wallets } = useWalletDetection();
const { connectDetected } = useWalletConnection(); // a GalaWalletProvider for Gala Wallet, an ExternalWalletProvider otherwise
const { address, galaAddress, isConnected } = useWallet();

The address follows the wallet (account switches, a wallet-side disconnect); the latest connect wins over a slower earlier one; a provider the context created is released when it is replaced, when its connect fails and on unmount; initialProvider is connected once. A hook outside <WalletProvider> is WALLET_CONTEXT_MISSING. It renders on the server (no window, nothing detected). ./react does not re-export the providers: import them from ./providers.

Every error core throws is a GalaSDKError with a stable code, flat params for an app's own localization and a phase (pre_send: nothing was transmitted). The codes are listed in docs/error-catalog.md. A product SDK's error class extends GalaSDKError and adds its own codes; isGalaError(error) recognises an error from any of them.

Gateway writes

import { GatewayWrites, PrivateKeySigner } from '@gala-chain/gala-core-sdk';

const writes = new GatewayWrites({
  gatewayBaseUrl: 'https://gateway-mainnet.galachain.com',
  signer: new PrivateKeySigner(process.env.GALACHAIN_PRIVATE_KEY!),
  walletAddress: 'eth|70997970C51812dc3A010C7d01b50e0d17dc79C8', // or a client| alias
});

const { transactionId, blockNumber } = await writes.transferGala({ to: 'client|abc', quantity: '1.5' });
await writes.lockTokens({ tokens: [{ tokenClassKey: 'GALA|Unit|none|none', quantity: '10' }], expires: 0 });
  • Quantities are WHOLE tokens, as the decimal string the chain receives; they are signed exactly as written ("1.50" stays "1.50") and never scaled.
  • Tokens: tokenClassKey (collection|category|type|additionalKey with exactly four parts, the $ composite key, or the object) plus instance (default "0"), or tokenName through an optional tokenNameResolver. A bare symbol is never a class key.
  • Identities (to, walletAddress, lockAuthority): an Ethereum account (eth|<40 hex>, 0x<40 hex>, bare hex; any casing but a wrong EIP-55 checksum) is always sent as eth|<checksummed>, the only spelling the gateway accepts; client|<id> is sent as written. eth|0x<hex> is not an address form: it is refused before anything is signed or sent with INVALID_ETH_USER_REF_PREFIX (an eth| reference takes the 40 digits with no 0x; the error's expected is the right spelling). A bare 0x<40 hex> is an ordinary Ethereum address and is converted.
  • The signer is handed the bare DTO; the body sent is exactly the DTO plus the signature (a signer that adds or changes a field is refused). A uniqueKey is minted per write unless you pass one.
  • Every DTO carries a dtoOperation (<channel>_<chaincode>_<Contract>:<Method>, for example asset-channel_basic-asset_GalaChainToken:TransferToken), set before the signer runs because it is part of what is signed. The chain refuses a DTO without it ("DTO operation is not provided. Signed requests must include dtoOperation.") or with one that is not the call it is sent to ("The dto was signed to call X operation, but the current operation is Y"). The URL of a write and its operation come from one table (CHAIN_CONTRACT_OPERATION_PREFIXES), so they cannot disagree. For a call the SDK does not make, use withDtoOperation(contractPath, method, dto) (the contract path is the route's <channel>/<contract>, such as asset/token-contract) or signPreSendFor(signer, contractPath, method, dto), which sets it and signs (signPreSend(signer, method, dto) keeps its 1.0.0 signature and signs the DTO as given); a DTO that already names a different operation is refused as SIGNING_FAILED. Never add it after signing: the signature would not cover it. Inside a launchpad bundle the operation is the bundler's BatchSubmit (asset-channel_basic-asset_Launchpad:BatchSubmit), not the inner DTO's own method: launchpad-sdk sets it.
  • Typed data (BrowserWalletSigner with { scheme: 'eip712' }, and the ./bridge bridge-out) is signed under an EIP-712 domain whose NAME the deployment must accept: the stage chain refuses anything but its own ("EIP-712 domain name must be GalaChainStage for this deployment."). Pass GALA_CHAIN_ENVIRONMENTS[env].eip712DomainName (GalaChainStage on stage; absent on prod, where a signer keeps the name it always signed: ethereum, and GalaConnect for the bridge) as the signer's eip712DomainName; BridgeService takes the environment's by itself. The chain id stays the wallet's live one.
  • GalaChain's Status is checked before anything else is trusted; a timeout or broken connection is GATEWAY_WRITE_OUTCOME_UNKNOWN: the write may have been applied, so check its uniqueKey and never resend it under a fresh key.

NFT writes

On the writes above:

import { getPublicKeyFromPrivateKey } from '@gala-chain/gala-core-sdk';

const claim = await writes.claimNftCollection({ collection: 'MyArt' });            // GrantNftCollectionAuthorization
await writes.createNftCollection({                                                  // CreateNftCollection
  collection: 'MyArt', category: 'Item', type: 'Sword',
  name: 'Sword', symbol: 'SWD', description: 'A sword', image: 'https://example.com/sword.png',
  maxSupply: '1000',                                                                // required: the chain refuses an unbounded NFT supply
});
const { tokenInstances } = await writes.mintNft({                                   // MintTokenWithAllowance (the minter grants itself the allowance)
  collection: 'MyArt', category: 'Item', type: 'Sword', quantity: '2',
});
const quote = await writes.estimateNftFee(                                          // the chain's DryRun, nothing is written
  { write: 'mintNft', collection: 'MyArt', category: 'Item', type: 'Sword', quantity: '2' },
  { callerPublicKey: getPublicKeyFromPrivateKey(process.env.GALACHAIN_PRIVATE_KEY!).compressedPublicKey },
);
console.log(quote.fee, quote.feeToken); // "1" "GALA" on stage; each environment has its own fees
  • Each write takes the checks of every core write (the input is refused before anything is signed or sent, INVALID_NFT_INPUT; a uniqueKey is minted per write unless you pass one, and a timeout is GATEWAY_WRITE_OUTCOME_UNKNOWN: retry with the SAME uniqueKey, never a fresh one).
  • The receipts carry what the chain answered, read and checked, never invented: collection and authorizedUsers of a claim, the tokenClass of a create, the tokenInstances of a mint (as many as asked for, of the class named, none twice; any other answer is GATEWAY_RESPONSE_INVALID).
  • authorizedUser, owner and authorities are user references (see the identities above); an eth| reference is stored by the chain under that account's client| alias. authorities and owner default to the writer when omitted.
  • The chain refuses a name another account holds (COLLECTION_NAME_ALREADY_CLAIMED for the same name in another casing, USER_NOT_AUTHORIZED_FOR_COLLECTION for one a different account was granted) but accepted a second claim of a name the SAME account already held (stage, 2026-11-04): a claim is not idempotent, so check availability first and retry only with the same uniqueKey (UNIQUE_TRANSACTION_CONFLICT refuses its replay).
  • mintNft is MintTokenWithAllowance unless existingAllowance: true (MintToken, which spends an allowance the writer already holds).
  • estimateNftFee prices the same input with the gateway's DryRun and needs the writer's public key (callerPublicKey, hex), because a signer is not asked for its own. The fee is the network's figure for THIS environment (stage charged 5 GALA for a claim, 5 for a create and 1 for a mint on 2026-11-04; the fixed fees of getNftCollectionClaimFee are mainnet's), and a write the chain would refuse is GATEWAY_READ_REJECTED, never a fee.

Gateway reads

import { GALA_CHAIN_ENVIRONMENTS, GatewayReads } from '@gala-chain/gala-core-sdk';

const reads = new GatewayReads({ gatewayBaseUrl: GALA_CHAIN_ENVIRONMENTS.prod.gatewayBaseUrl });

const gala = await reads.fetchTokenBalance({ owner: 'client|abc', tokenClassKey: 'GALA|Unit|none|none' });
console.log(gala?.quantity, gala?.lockedQuantity, gala?.availableQuantity); // whole-token strings

const { symbol, decimals } = await reads.fetchTokenDetails('GUSDC|Unit|none|none');
const classes = await reads.fetchAllTokenClasses({ collection: 'BONKTactics' }, { maxPages: 10 });
  • Reads are unsigned and apply nothing: every failure after the request left says so (error.write === false), and a retry is always safe.
  • Owners are spelled as the writes spell them (an Ethereum account in any form as eth|<checksummed>, client| as written); class keys are accepted in the same forms. $MUSIC balances are read on the gateway's music channel.
  • Every answer is checked (GalaChain's Status, then each row) before it is returned; a balance of another owner than the one asked for is refused. Quantities stay the chain's whole-token decimal strings; hold totals are exact and never in exponent form.
  • A token class that does not exist is TOKEN_CLASS_NOT_FOUND; a fetchAll... read that would need more than maxPages pages is PAGINATION_LIMIT_EXCEEDED (never a truncated list).
  • fetchPublicKey(user) reads the key GalaChain has registered for a user ({ publicKey, signing? }, undefined when none is saved). The public gateways do not route the public-key-contract; read it through a connect-api proxy: new GatewayReads({ gatewayBaseUrl: 'https://api-galaswap.gala.com/galachain' }).

Signing parity

The signing code is pinned byte-for-byte to @gala-chain/api and to the Gala Wallet's and the gSwap web app's signing code by the golden vectors in tests/fixtures/wallet-signing-golden.json and tests/fixtures/frontend-signing-golden.json (tests/signing-golden.test.ts). They are never regenerated to make a test pass. Those two pin the signing primitives and the web apps' bytes, which carry no dtoOperation; the SDK's own write and bridge recordings (tests/fixtures/writes-signing-golden.json, bridge-out-recorded.json) pin the signed bodies including it.

React Native

The shipped source uses no Node builtin, no Buffer, no process, and never loads ethers, axios or @gala-chain/api (pnpm run check:rn-safety, also run by the test suite). The only polyfill React Native/Hermes needs is crypto.getRandomValues, for minting uniqueKeys and new random wallets (createWallet()):

import 'react-native-get-random-values'; // once, before the SDK mints a key

Without it, minting a key or a wallet throws CSPRNG_UNAVAILABLE (never a weaker fallback).

./bridge is the exception: it loads ethers, @solana/web3.js and @solana/spl-token, and an app that imports it on React Native also installs what those libraries ask for there (crypto.getRandomValues above, which createSolanaWallet needs too; @solana/web3.js's React Native guidance adds a global Buffer from the buffer package). Core's own ./bridge code uses no Buffer or process global (Solana instruction data are Uint8Arrays) and touches none at module load: the guard allows ./bridge exactly those three packages and nothing else (base58 is @scure/base, pure JS like the rest of core).

Bundle size

sideEffects: false, and the browser build is one file per source module, so an app (or a product SDK's light module) that imports one helper loads that module only. @gala-chain/gala-core-sdk/wallet holds only the dependency-free wallet helpers (about 1.2 kB minified, capped at 2 kB). tests/tree_shaking.test.ts budgets every shell-safe helper. The browser builds of ./providers (about 17 kB minified, 7.6 kB gzipped, most of it the known wallets' icons), ./react (about 4 kB, 1.7 kB gzipped) and ./bridge (about 60 kB minified, 16 kB gzipped, before ethers and @solana/*) are loaded only by an app that imports them.

Status

1.2.1 (1.2: NFT collection reads and fee estimates, the NFT writes

claimNftCollection, createNftCollection and mintNft on GatewayWrites, and their DryRun fee quote estimateNftFee; rc.7: eth|0x<hex> is refused as INVALID_ETH_USER_REF_PREFIX, not an address form; rc.6: fetchPublicKey, MetaMask and Trust Wallet detection, silent restore(); rc.5: every Ethereum account a read, write or GalaConnect client sends is eth|<EIP-55>, the only spelling the gateway accepts, and galaChainUserRef is exported; rc.4: bridgeableTokenService is required). In: signing, signers, transport and the error model (rc.0, from gswap-sdk); the gateway token writes (rc.1, from launchpad-sdk's transfer and lock services, which now delegate here); the gateway token reads (rc.2: balances, token classes, NFT collection authorizations, from launchpad-sdk's balance and token services, which now delegate here) and the deployment endpoints; the wallet providers (./providers), React hooks (./react), wallet helpers (createWallet and the key derivations) and the bridge (./bridge: bridging, the token lists, wrap / unwrap, createSolanaWallet) (rc.3, from launchpad-sdk's /wallet, /react, helpers/wallet, bridge/ and its bridgeable / wrappable token and wrap services, which are gone).

Migrating from gswap-sdk 1.x

See MIGRATING-FROM-GSWAP.md: every moved export, old path to new path, and the renamed error and brand identifiers.

License

Apache License 2.0.

版本与发布记录

@gala-chain/gala-core-sdk 共发布 23 个版本,首次发布于 2026/10/15;过去 12 个月发布了 23 个版本。

版本发布日期距今
1.2.1latest2026/11/106 天前
1.2.02026/11/106 天前
1.2.0-beta.42026/11/0610 天前
1.2.0-beta.32026/11/0610 天前
1.2.0-beta.22026/11/0610 天前
1.2.0-beta.12026/11/0511 天前

关于 @gala-chain/gala-core-sdk 的常见问题

@gala-chain/gala-core-sdk 是什么?

The GalaChain core SDK: signing (native, personal-sign, EIP-712), the gateway transport, the gateway token reads (balances, token classes, NFT collections) and writes (transfer, burn, lock, unlock) and the shared error model, for every product SDK and app

如何安装 @gala-chain/gala-core-sdk?

在项目目录运行 npm install @gala-chain/gala-core-sdk,或使用 pnpm add / yarn add / bun add。

@gala-chain/gala-core-sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@gala-chain/gala-core-sdk 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@gala-chain/gala-core-sdk 可以商用吗?

@gala-chain/gala-core-sdk 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@gala-chain/gala-core-sdk 的下载量有多少?

根据 npm 官方下载统计,@gala-chain/gala-core-sdk 在 2026/10/16 – 2026/11/14 这 30 天内被下载 4,762 次,日均约 159 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@gala-chain/gala-core-sdk 还在维护吗?

最新版本 1.2.1 发布于 2026/11/10(6 天前);至今共发布 23 个版本,其中过去 12 个月发布了 23 个;首次发布于 2026/10/15。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。