Decentralized SQL queries and blockchain data via Space and Time for W3 workflows. ZK-proven query results over indexed chain data and custom tables.
- uses: w3-io/w3-sxt-action@v0
id: blocks
with:
command: query
api-key: ${{ secrets.SXT_API_KEY }}
schema-name: ETHEREUM
sql: >
SELECT BLOCK_NUMBER, TIME_STAMP, TRANSACTION_COUNT
FROM ETHEREUM.BLOCKS
ORDER BY BLOCK_NUMBER DESC LIMIT 5
- run: echo "${{ steps.blocks.outputs.result }}"- uses: w3-io/w3-sxt-action@v0
with:
command: ddl
user-id: ${{ secrets.SXT_USER_ID }}
password: ${{ secrets.SXT_PASSWORD }}
biscuit-name: ${{ secrets.SXT_BISCUIT_NAME }}
api-url: https://api.makeinfinite.dev
proxy-url: https://proxy.api.makeinfinite.dev
schema-name: MY_APP
sql: >
CREATE TABLE MY_APP.events (id INT PRIMARY KEY, name VARCHAR)
WITH "public_key=${{ secrets.SXT_TABLE_PUBLIC_KEY }},access_type=public_read"One-time setup for login mode — generates the resource keypair, creates the biscuit, and registers it on the Make Infinite proxy:
npm run generate-biscuit -- \
--resources=my_app.events \
--biscuit-name=my-app-events \
--user-id=$SXT_USER_ID \
--password=$SXT_PASSWORDPaste the printed public_key hex into SXT_TABLE_PUBLIC_KEY and the name into SXT_BISCUIT_NAME. Resource names must be lowercase — SxT normalizes references when evaluating biscuits.
| Command | Description |
|---|---|
query |
Execute a SELECT query, returns JSON rows |
execute |
Execute DML (INSERT, UPDATE, DELETE) |
ddl |
Execute DDL (CREATE TABLE, DROP TABLE, ALTER) |
list-tables |
(not supported — SxT has no SHOW TABLES) |
list-chains |
Query latest blocks from an indexed blockchain |
put-entity |
Append a new entity version (append-only, merge + CAS) |
get-entity |
Read the latest version of an entity by id, tenant-scoped |
query-entities |
PostgREST-style filter/sort/limit over the latest versions |
transaction |
NOT_SUPPORTED (SxT has no multi-entity transaction) |
object-store-* |
NOT_SUPPORTED (object storage is the cloud: syscall) |
See docs/state-commands.md for the append-only
entity model, the ENTITY_VERSIONS bootstrap DDL, seed rows, and biscuit scoping.
| Name | Required | Default | Description |
|---|---|---|---|
command |
Yes | Operation to perform | |
schema-name |
Yes | Default schema for resource scoping (e.g. ETHEREUM, myapp) |
|
api-url |
No | https://proxy.api.makeinfinite.dev |
SQL endpoint (use https://api.makeinfinite.dev for login mode) |
proxy-url |
No | https://proxy.api.makeinfinite.dev |
Login + biscuit lookup endpoint |
api-key |
No | SxT API key — read-only indexed chain data | |
auth-url |
No | Custom JWT endpoint URL (alternative to api-key) | |
auth-secret |
No | Shared secret for custom JWT endpoint | |
user-id |
No | SxT userId (email) for login mode | |
password |
No | SxT password for login mode | |
biscuit-name |
No | Named biscuit on the proxy — fetched at runtime | |
biscuit |
No | Pre-fetched biscuit string (alternative to biscuit-name) |
|
origin-app |
No | w3-sxt-action |
Application identifier for request tracking |
sql |
No | SQL statement to execute | |
resources |
No | Comma-separated table references for performance optimization | |
query-type |
No | OLTP |
Query type for DQL: OLTP or OLAP |
chain |
No | Blockchain name for list-chains (e.g. ethereum) |
|
tenant-id |
No* | Tenant scope for state commands (bound on every read/write) | |
entity-type |
No* | Entity type for state commands (e.g. Gift, User) |
|
id |
No* | Entity id for put-entity / get-entity |
|
fields |
No* | JSON entity / partial patch for put-entity |
|
expected-version |
No | Optimistic-concurrency token for put-entity |
|
filter |
No | JSON PostgREST-style filter for query-entities |
|
sort |
No | JSON [{field, direction}] for query-entities |
|
limit |
No | 50 |
Max rows for query-entities (capped at 500) |
max-retries |
No | 3 |
Maximum retry attempts |
retry-delay |
No | 2 |
Base retry delay in seconds |
timeout |
No | 30 |
Request timeout in seconds |
| Name | Description |
|---|---|
result |
JSON result of the operation |
error-code |
Typed code on failure: NOT_SUPPORTED / RATE_LIMITED / UPSTREAM_FAILURE / INVALID_INPUT / NOT_FOUND / PRECONDITION_FAILED |
* tenant-id / entity-type / id / fields are required for the state
commands (put-entity / get-entity / query-entities) but not for the SQL or
discovery commands — hence "No*" above. Empty values raise a typed
INVALID_INPUT rather than a generic failure.
The secret names shown above (SXT_USER_ID, SXT_PASSWORD,
SXT_BISCUIT_NAME, SXT_TABLE_PUBLIC_KEY, SXT_API_KEY) are
illustrative — name your repository secrets whatever you like. The
action-input names on the left side of with: (e.g. user-id,
password, biscuit-name, api-key) are the fixed part of the
contract; anything on the right side of ${{ secrets.… }} is yours
to choose.
The action has three auth modes, resolved in this priority order:
- Login — set
user-id+password+biscuit-name. The action logs in to the Make Infinite proxy, fetches the named biscuit, and executes SQL againstapi-urlwithBearer <jwt>and the biscuit in the request body. This is the only path that supports DDL and writes. Pointapi-urlathttps://api.makeinfinite.dev(the direct SQL endpoint) — the proxy's/v1/sqlrequires an apikey header even with Bearer auth and will reject login-mode writes. - Explicit JWT — set
auth-url+auth-secret(with optionalbiscuit). Useful when you have a custom token service fronting SxT. - API key — set
api-keyonly. Works against the Make Infinite Gateway Proxy for read-only access to SxT-managed indexed chain data. DDL and writes are not supported in this mode.
See scripts/generate-biscuit.mjs for the one-time setup helper that creates the keypair, signs the biscuit, and registers it on the proxy.