Tags: GalaChain/sdk
Tags
Token Instance Metadata (#787) * Token Instance Metadata * Regenerate chaincode-template API snapshots after merging main Main added an OTEL `trace` property to every SubmitCallDTO schema. Git auto-merged the two template snapshots cleanly, but the branch-added TokenInstanceMetadata DTO schemas were generated before that change, so they were left without `trace` (91 trace vs 108 uniqueKey properties). Regenerated both snapshots against the local SDK via npm-pack-and-replace. Purely additive; PublicKeyContract and AppleContract snapshots reproduced byte-identical. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Harden token instance metadata validation and state reads Addresses the non-authorization findings from review of this branch. - fetchTokenInstanceMetadataProject and setTokenInstanceMetadata read through objectExists() + getObjectByKey() instead of .catch(() => undefined). Only a missing record now resolves to undefined; a deserialization or stub failure propagates. Previously any read error made an owned project look unowned (silently reassigning ownership to the caller) or discarded createdBy/created on update. Matches the idiom in nftCollections/authorization.ts. - Cap attributes and customFields at 100 entries on both the chain object and the submit DTO, bounding the size of a single write. - background_color is validated against /^[0-9a-fA-F]{6}$/ rather than only MaxLength(6), matching its documented format. - FetchTokenInstanceMetadataWithPaginationDto.instance must be a canonical unsigned integer. Composite keys are built from BigNumber.toString(), so "01" or "1.0" previously returned an empty page instead of an error. Also validated when passed without project. - The unpaginated fetch pages one past a 1000-document cap and throws TooManyMetadataDocumentsError, instead of accumulating an unbounded attacker-influenced result set until the global 100k limit rejects every call. Adds chain-api/src/types/TokenInstanceMetadata.spec.ts covering the new constraints, and regenerates the chaincode-template API snapshots for the resulting schema changes (maxItems, pattern). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * snake case updates * Gate token instance metadata on NFT collection name authorization --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Fix: Persist uniqueKey when a submit transaction fails (#810) * Fix: Persist uniqueKey when a submit transaction fails Failed inner batch ops and failed standalone submits left uniqueKeys unspent. Consume UNTX writes even on Error; business writes still roll back. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix lockNFT e2e to use a fresh uniqueKey per unlock submit. Failed unlock attempts now consume their uniqueKey, so the authority retry must not reuse the same DTO. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Jehosephat <jeganhouse@gala.games>
Guards against EIP-712 unsigned-field injection (#808) * Guards against EIP-712 unsigned-field injection * fix(auth): reject EIP-712 DTOs with fields not covered by the signed types Closes the unsigned-field-injection / cross-type signature-replay class behind the 2026-08-18 mainnet drain. getPayloadToSign() hashes an EIP-712 DTO via TypedDataEncoder.encode(domain, types, value), which covers ONLY the fields enumerated in `types` — and `types` travels inside the DTO, supplied by the caller. Any DTO field not declared in `types[primaryType]` (or its nested struct type) is therefore NOT signed. A signature produced for one DTO type could be replayed against another: a GalaSwap Swap/AddLiquidity/CollectPositionFees signature (whose types omit `to`/`quantity`/ `tokenInstance`) replayed into GalaChainToken:TransferToken with attacker-injected `to`/`quantity`. The recovered signer is unchanged (the victim), so the transfer takes the owner path (no allowance check) and drains the victim. Fix: before returning the signing payload, assert that every message field present on the value is declared in its EIP-712 struct type, recursively (domain/types are envelope members and exempt; signature/multisig/trace/prefix are already stripped). A replayed cross-type signature carries `types` that do not match the DTO it was replayed into, so the injected fields are undeclared and this throws BEFORE the signer is trusted. Fully-declared legitimate DTOs are unaffected. Tests: legit fully-declared DTO still produces a payload; a Swap-typed DTO with injected to/quantity/tokenInstance is rejected; a field injected into a nested struct is rejected. Full chain-api utils+types suite (304 tests) green; tsc -b ok. Follow-up hardening (separate, not in this commit): (2) bind the signed primaryType to the invoked method server-side; (3) stop defaulting `from` to callingUser on the submit path in the token chaincode. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
PreviousNext