{"id":48646141,"url":"https://github.com/aibtcdev/tx-schemas","last_synced_at":"2026-04-15T20:07:29.454Z","repository":{"id":348562940,"uuid":"1196650198","full_name":"aibtcdev/tx-schemas","owner":"aibtcdev","description":"Shared transaction schemas, state models, and response types for AIBTC services.","archived":false,"fork":false,"pushed_at":"2026-04-10T00:42:21.000Z","size":171,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-10T01:24:22.304Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aibtcdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-30T22:52:00.000Z","updated_at":"2026-04-10T00:42:14.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/aibtcdev/tx-schemas","commit_stats":null,"previous_names":["aibtcdev/tx-schemas"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/aibtcdev/tx-schemas","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aibtcdev%2Ftx-schemas","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aibtcdev%2Ftx-schemas/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aibtcdev%2Ftx-schemas/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aibtcdev%2Ftx-schemas/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aibtcdev","download_url":"https://codeload.github.com/aibtcdev/tx-schemas/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aibtcdev%2Ftx-schemas/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31857679,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-15T15:24:51.572Z","status":"ssl_error","status_checked_at":"2026-04-15T15:24:39.138Z","response_time":63,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-10T04:08:26.519Z","updated_at":"2026-04-15T20:07:29.441Z","avatar_url":"https://github.com/aibtcdev.png","language":"TypeScript","readme":"# @aibtc/tx-schemas\n\nShared zod schemas for AIBTC payment state models, first-party relay RPC schemas,\nand external x402 HTTP schemas.\n\n## Install\n\n```bash\nnpm install @aibtc/tx-schemas zod\n```\n\n## Package Shape\n\n- `@aibtc/tx-schemas` exports the full surface\n- `@aibtc/tx-schemas/core` exports canonical payment enums, terminal reasons, and shared primitives\n- `@aibtc/tx-schemas/rpc` exports internal relay service-binding schemas\n- `@aibtc/tx-schemas/http` exports external x402 facilitator and polling schemas\n- `@aibtc/tx-schemas/news` exports shared editorial/newsroom schemas, including beat lifecycle transition contracts\n\n## Usage\n\n```ts\nimport { PaymentStateSchema, PaymentStateCategoryByState } from \"@aibtc/tx-schemas/core\";\nimport { RpcSubmitPaymentResultSchema } from \"@aibtc/tx-schemas/rpc\";\nimport { HttpSettleRequestSchema } from \"@aibtc/tx-schemas/http\";\nimport { TERMINAL_REASONS } from \"@aibtc/tx-schemas/terminal-reasons\";\n\nconst state = PaymentStateSchema.parse(\"confirmed\");\nconst category = PaymentStateCategoryByState[state];\nconst terminalReasons = TERMINAL_REASONS;\n\nconst rpcResult = RpcSubmitPaymentResultSchema.parse({\n  accepted: true,\n  paymentId: \"pay_01J7QZXK5XRGBVMK3N9RTNF4WW\",\n  status: \"queued\",\n});\n\nconst settleRequest = HttpSettleRequestSchema.parse({\n  paymentPayload: {\n    x402Version: 2,\n    payload: { transaction: \"0x1234\" },\n  },\n  paymentRequirements: {\n    scheme: \"exact\",\n    network: \"stacks:2147483648\",\n    amount: \"1000000\",\n    asset: \"STX\",\n    payTo: \"ST000000000000000000002AMW42H\",\n  },\n});\n```\n\n## Subpath Imports\n\n- `@aibtc/tx-schemas`\n- `@aibtc/tx-schemas/core`\n- `@aibtc/tx-schemas/core/enums`\n- `@aibtc/tx-schemas/core/schemas`\n- `@aibtc/tx-schemas/core/primitives`\n- `@aibtc/tx-schemas/terminal-reasons`\n- `@aibtc/tx-schemas/core/terminal-reasons`\n- `@aibtc/tx-schemas/rpc`\n- `@aibtc/tx-schemas/http`\n- `@aibtc/tx-schemas/news`\n\n## Schema Rules\n\n- Canonical payment states live in `core` and are the only shared payment-state source of truth.\n- Public canonical states are `requires_payment`, `queued`, `broadcasting`, `mempool`, `confirmed`, `failed`, `replaced`, and `not_found`.\n- `submitted` is reserved for relay internals and must not appear in the caller-facing contract.\n- `rpc` and `http` may differ in field names and transport ergonomics, but they must reuse the same state semantics.\n- The default protected-resource delivery invariant is `deliver-only-on-confirmed`.\n- Any product that delivers on in-flight states should document that as an application exception, not a canonical package rule.\n- `paymentId` is relay-owned and duplicate submission should reuse the same `paymentId` until terminal resolution.\n- `payment-identifier` is client-supplied idempotency input only. It must not be treated as canonical public `paymentId`.\n- Accepted duplicate submit responses should return the current caller-facing in-flight status for that `paymentId`: `queued`, `broadcasting`, or `mempool` as applicable.\n- `queued_with_warning` remains an RPC-only temporary compatibility shim for warning-aware callers during migration.\n- Polling contracts may surface `checkStatusUrl` as an additive convenience field, and internal/external polling should treat it as another way to reach the same `paymentId` lifecycle.\n- If a downstream consumer has neither relay `paymentId` nor canonical `checkStatusUrl`, it must fail closed instead of inventing a polling identity.\n- Terminal polling responses should carry a normalized `terminalReason` when one is known, even if transports also emit local error codes.\n- Machine-readable contract exports for downstream repos include `CanonicalDomainBoundary`, `CANONICAL_POLLING_IDENTITY_FIELDS`, `RELAY_LIFECYCLE_BRIDGE`, and `TERMINAL_REASON_CATEGORY_HANDLING`.\n\nMore detail lives in [docs/package-schemas.md](docs/package-schemas.md),\n[docs/boring-state-machine-contract.md](docs/boring-state-machine-contract.md),\n[docs/x402-approval-spec.md](docs/x402-approval-spec.md), and\n[docs/x402-state-machines.md](docs/x402-state-machines.md).\n\n## Consuming sponsor wallet helpers\n\nThe `core` export ships pure state-machine helpers so that every service that\ntouches a sponsor wallet (`/sponsor`, `/relay`, `/settle`, …) drives off the\nsame primitives instead of re-implementing the nonce-conflict logic inline.\n\nThe canonical cycle is: classify what is at the nonce, decide what to do,\napply the decision to state, reconcile periodically against the mempool.\n\n```ts\nimport {\n  classifyOccupant,\n  decideBroadcast,\n  adoptOrphan,\n  quarantine,\n  reconcile,\n  type HiroSponsorTxView,\n  type SponsorLedger,\n  type WalletCapacity,\n} from \"@aibtc/tx-schemas/core\";\n\nfunction handleConflict(\n  wallet: WalletCapacity,\n  ledger: SponsorLedger,\n  nonce: number,\n  mempoolHit: HiroSponsorTxView | null,\n  sponsorAddress: string\n) {\n  const occupant = classifyOccupant(mempoolHit, sponsorAddress, ledger, nonce);\n\n  const decision = decideBroadcast(\n    wallet,\n    { outcome: \"nonce_conflict\", isOrigin: false },\n    { nonce, ledger, occupant }\n  );\n\n  switch (decision.kind) {\n    case \"rbf_with_fee\":\n      // re-sign at decision.fee, broadcast\n      return wallet;\n    case \"adopt_then_rbf\":\n      // `adopt_then_rbf` is only emitted when the occupant was classified as\n      // `sponsor_owned_orphan`, which requires a non-null mempool hit.\n      return adoptOrphan(wallet, mempoolHit!);\n    case \"quarantine\":\n      return quarantine(wallet, decision.nonce, decision.reason, {\n        txId: occupant.kind !== \"untraceable\" ? occupant.txId : undefined,\n      });\n    case \"terminal\":\n      // mark the payment terminal with decision.reason\n      return wallet;\n    case \"first_broadcast\":\n      return wallet;\n  }\n}\n\n// Periodic reconciliation pass adopts unrecorded sponsor txs and flags drops:\nconst { wallet: next, ledger: nextLedger, adopted, dropped } = reconcile(\n  wallet,\n  ledger,\n  mempoolReadByNonce,\n  sponsorAddress\n);\n```\n\nAll helpers are pure: inputs → new state. No I/O, and time-sensitive helpers\naccept an injectable `now` option for deterministic tests; otherwise they use\nthe current time by default.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faibtcdev%2Ftx-schemas","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faibtcdev%2Ftx-schemas","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faibtcdev%2Ftx-schemas/lists"}