|
Some checks failed
E2E Tests / test-e2e (push) Failing after 1h21m21s
Integration Tests / test-integration (push) Successful in 2h13m47s
SDK Tests / sdk_tests_authority_auctions (push) Failing after 3h11m11s
SDK Tests / sdk_tests (push) Failing after 3h11m10s
SDK Tests / sdk_tests_nameservice_expiry (push) Failing after 3h11m11s
Unit Tests / test-unit (push) Failing after 3h14m50s
Applications built on laconicd repeatedly pick the Record + attribute-
scan pattern for data that has mutable logical identity (game state,
user profiles, inventories). The query cost then grows linearly with
per-entity version count, and the fix reached for (cache, pagination,
compaction) hides the design mistake rather than correcting it. AI
agents hit this failure mode especially reliably: they pattern-match
the existing client's queryRecords usage as canon and never discover
the Naming API.
This commit adds four pieces of documentation that surface the right
primitive *before* a wrong one is committed to:
* docs/PATTERNS.md — primitive decision tree with concrete
anti-patterns (queryRecords-as-KV, compaction-for-latency,
cache-the-slow-query) and a worked example (mutable game state).
* AGENTS.md — explicit for AI coding agents; names the failure mode,
lists six rules, and tells agents to read PATTERNS.md before
writing their first queryRecords call.
* gql/cerc-io/laconicd/schema.graphql — prescriptive comments on
queryRecords (warning against mutable-identity usage),
getRecordsByIds (point-lookup clarification), and the Naming
API section (USE THIS for current-state lookups).
* README.md — new 'Designing state that lives on laconicd' section
between Usage and Tests, linking both new docs.
|
||
|---|---|---|
| .. | ||
| cerc-io/laconicd | ||
| flags.go | ||
| generated.go | ||
| gqlgen.yml | ||
| graphiql.go | ||
| models_gen.go | ||
| README.md | ||
| resolver.go | ||
| scalar.go | ||
| server.go | ||
| status.go | ||
| util.go | ||
| version.go | ||
cerc-io laconic gql
Browser : http://localhost:9473 for gql
Run gqlgen
On having some change in the GQL schema (for example: adding a new query) update the schema.graphql file as required and run the following:
-
Generate GQL bindings:
# Install gqlgen if not present go get github.com/99designs/gqlgen@v0.17.22 # Generate bindings cd gql go run github.com/99designs/gqlgen generate -
Implement the required resolver method(s)
-
Regenerate GQL bindings:
# Generate bindings go run github.com/99designs/gqlgen generate
Start server
laconicd start --gql-playground --gql-server
Basic node status:
{
getStatus {
version
node {
id
network
moniker
}
sync {
latestBlockHeight
catchingUp
}
numPeers
peers {
isOutbound
remoteIp
}
diskUsage
}
}
Full node status:
{
getStatus {
version
node {
id
network
moniker
}
sync {
latestBlockHash
latestBlockTime
latestBlockHeight
catchingUp
}
validator {
address
votingPower
proposerPriority
}
validators {
address
votingPower
proposerPriority
}
numPeers
peers {
node {
id
network
moniker
}
isOutbound
remoteIp
}
diskUsage
}
}
Get records by IDs.
{
getRecordsByIds(ids: ["bafyreigswvbm4dbpnbwkyegrcxd6kynqe4bivflo6esedgxnuofpzonwdy"]) {
id
names
bondId
createTime
expiryTime
owners
attributes {
key
value {
string
}
}
}
}
Query records.
{
queryRecords(attributes: [{ key: "type", value: { string: "crn:bot" } }]) {
id
names
bondId
createTime
expiryTime
owners
attributes {
key
value {
string
}
}
}
}
Get account details:
{
getAccounts(addresses: ["laconic17t5ywvqxntu0afc96tz0yxcx92ss0e2alhx2c2"]) {
address
pubKey
number
sequence
balance {
type
quantity
}
}
}
Query bonds:
{
queryBonds(
attributes: [
{
key: "owner"
value: { string: "laconic17t5ywvqxntu0afc96tz0yxcx92ss0e2alhx2c2" }
}
]
) {
id
owner
balance {
type
quantity
}
}
}
Get bonds by IDs.
{
getBondsByIds(
ids: [
"1c2b677cb2a27c88cc6bf8acf675c94b69051125b40c4fd073153b10f046dd87"
"c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440"
]
) {
id
owner
balance {
type
quantity
}
}
}
Query Bonds by Owner
{
queryBondsByOwner(
ownerAddresses: ["laconic17t5ywvqxntu0afc96tz0yxcx92ss0e2alhx2c2"]
) {
owner
bonds {
id
owner
balance {
type
quantity
}
}
}
}
Query auctions by ids
{
getAuctionsByIds(
ids: ["be98f2073c246194276554eefdb4c95b682a35a0f06fbe619a6da57c10c93e90"]
) {
id
ownerAddress
createTime
minimumBid {
type
quantity
}
commitFee {
type
quantity
}
commitsEndTime
revealFee {
type
quantity
}
revealsEndTime
winnerBid {
type
quantity
}
winnerPrice {
type
quantity
}
winnerAddress
bids {
bidderAddress
commitHash
commitTime
commitFee {
type
quantity
}
revealFee {
type
quantity
}
revealTime
bidAmount {
type
quantity
}
status
}
}
}
LookUp Authorities
{
lookupAuthorities(names: []) {
ownerAddress
ownerAddress
height
bondId
status
expiryTime
auction {
id
ownerAddress
createTime
minimumBid {
type
quantity
}
commitFee {
type
quantity
}
commitsEndTime
revealFee {
type
quantity
}
revealsEndTime
winnerBid {
type
quantity
}
winnerPrice {
type
quantity
}
winnerAddress
bids {
bidderAddress
commitHash
commitTime
commitFee {
type
quantity
}
revealFee {
type
quantity
}
revealTime
bidAmount {
type
quantity
}
status
}
}
}
}
LookUp Names
{
lookupNames(names: ["crn://hello/test"]) {
latest {
id
height
}
history {
id
height
}
}
}
Resolve Names
{
resolveNames(names: ["asd"]) {
id
names
bondId
createTime
expiryTime
owners
attributes {
key
value {
string
}
}
}
}
Query participants:
{
getParticipants {
cosmosAddress
nitroAddress
}
}