@secondlayer/shared 6.28.0 → 6.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/db/index.d.ts +40 -2
- package/dist/src/db/index.js +3 -1
- package/dist/src/db/index.js.map +3 -3
- package/dist/src/db/queries/chain-reorgs.d.ts +35 -1
- package/dist/src/db/queries/chain-reorgs.js +3 -1
- package/dist/src/db/queries/chain-reorgs.js.map +3 -3
- package/dist/src/db/queries/contracts.d.ts +35 -1
- package/dist/src/db/queries/integrity.d.ts +35 -1
- package/dist/src/db/queries/subgraph-gaps.d.ts +35 -1
- package/dist/src/db/queries/subgraph-operations.d.ts +35 -1
- package/dist/src/db/queries/subgraphs.d.ts +43 -2
- package/dist/src/db/queries/subgraphs.js +11 -1
- package/dist/src/db/queries/subgraphs.js.map +4 -4
- package/dist/src/db/queries/subscriptions.d.ts +35 -1
- package/dist/src/db/schema.d.ts +38 -2
- package/dist/src/errors.d.ts +11 -2
- package/dist/src/errors.js +13 -2
- package/dist/src/errors.js.map +3 -3
- package/dist/src/index.d.ts +62 -3
- package/dist/src/index.js +99 -38
- package/dist/src/index.js.map +6 -6
- package/dist/src/node/hiro-client.d.ts +15 -1
- package/dist/src/node/hiro-client.js +10 -1
- package/dist/src/node/hiro-client.js.map +3 -3
- package/dist/src/node/local-client.d.ts +35 -1
- package/dist/src/schemas/index.d.ts +10 -0
- package/dist/src/schemas/index.js +3 -2
- package/dist/src/schemas/index.js.map +3 -3
- package/dist/src/schemas/subgraphs.d.ts +10 -0
- package/dist/src/schemas/subgraphs.js +3 -2
- package/dist/src/schemas/subgraphs.js.map +3 -3
- package/dist/src/subgraphs/spec.d.ts +3 -0
- package/dist/src/subgraphs/spec.js +83 -36
- package/dist/src/subgraphs/spec.js.map +3 -3
- package/dist/src/x402.d.ts +38 -0
- package/dist/src/x402.js +74 -0
- package/dist/src/x402.js.map +10 -0
- package/migrations/0090_events_streams_filter_idx.ts +72 -0
- package/migrations/0091_x402_payments.ts +41 -0
- package/migrations/0092_subgraph_visibility.ts +33 -0
- package/migrations/0093_ghost_accounts.ts +47 -0
- package/package.json +6 -2
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type Kysely, sql } from "kysely";
|
|
2
|
+
import { onControlPlane } from "../src/db/migration-role.ts";
|
|
3
|
+
|
|
4
|
+
// x402 payment ledger. Accountless x402 payers are entirely outside the
|
|
5
|
+
// account-keyed usage/billing path (countApiRequests / emitMeterEvent / freeze
|
|
6
|
+
// all short-circuit on a missing accountId), so per-payment accounting needs its
|
|
7
|
+
// own table — keyed by the challenge nonce + settled txid, not account_id.
|
|
8
|
+
// Control-plane (TARGET): written by the API on settle, read by reconcilers.
|
|
9
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
10
|
+
await sql`SET lock_timeout = '30s'`.execute(db);
|
|
11
|
+
await onControlPlane(async () => {
|
|
12
|
+
await sql`
|
|
13
|
+
CREATE TABLE x402_payments (
|
|
14
|
+
id BIGSERIAL PRIMARY KEY,
|
|
15
|
+
nonce TEXT NOT NULL UNIQUE,
|
|
16
|
+
txid TEXT NOT NULL UNIQUE,
|
|
17
|
+
asset TEXT NOT NULL,
|
|
18
|
+
amount TEXT NOT NULL,
|
|
19
|
+
payer TEXT NOT NULL,
|
|
20
|
+
surface TEXT NOT NULL,
|
|
21
|
+
state TEXT NOT NULL DEFAULT 'pending'
|
|
22
|
+
CHECK (state IN ('pending', 'confirmed', 'reverted')),
|
|
23
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
24
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
25
|
+
)
|
|
26
|
+
`.execute(db);
|
|
27
|
+
// Velocity/abuse queries scan by payer; reconcilers scan by state.
|
|
28
|
+
await sql`CREATE INDEX x402_payments_payer_idx ON x402_payments (payer)`.execute(
|
|
29
|
+
db,
|
|
30
|
+
);
|
|
31
|
+
await sql`CREATE INDEX x402_payments_state_idx ON x402_payments (state)`.execute(
|
|
32
|
+
db,
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
38
|
+
await onControlPlane(async () => {
|
|
39
|
+
await sql`DROP TABLE IF EXISTS x402_payments`.execute(db);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type Kysely, sql } from "kysely";
|
|
2
|
+
import { onControlPlane } from "../src/db/migration-role.ts";
|
|
3
|
+
|
|
4
|
+
// Subgraph read visibility. 'public' = anon-readable on /v1/subgraphs/:name
|
|
5
|
+
// (wildcard CORS, anon rate limits); 'private' = reads require the owning
|
|
6
|
+
// account's bearer key, anon resolution 404s. Existing rows default 'private'
|
|
7
|
+
// so nothing already deployed becomes world-readable; the public default for
|
|
8
|
+
// new managed deploys is applied at the API layer, not here. Public names are
|
|
9
|
+
// a single global namespace (claim-on-publish), enforced by the partial
|
|
10
|
+
// unique index. Control-plane (TARGET).
|
|
11
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
12
|
+
await sql`SET lock_timeout = '30s'`.execute(db);
|
|
13
|
+
await onControlPlane(async () => {
|
|
14
|
+
await sql`
|
|
15
|
+
ALTER TABLE subgraphs
|
|
16
|
+
ADD COLUMN visibility TEXT NOT NULL DEFAULT 'private'
|
|
17
|
+
CHECK (visibility IN ('public', 'private'))
|
|
18
|
+
`.execute(db);
|
|
19
|
+
await sql`
|
|
20
|
+
CREATE UNIQUE INDEX subgraphs_public_name_uidx
|
|
21
|
+
ON subgraphs (name) WHERE visibility = 'public'
|
|
22
|
+
`.execute(db);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
27
|
+
await onControlPlane(async () => {
|
|
28
|
+
await sql`DROP INDEX IF EXISTS subgraphs_public_name_uidx`.execute(db);
|
|
29
|
+
await sql`ALTER TABLE subgraphs DROP COLUMN IF EXISTS visibility`.execute(
|
|
30
|
+
db,
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type Kysely, sql } from "kysely";
|
|
2
|
+
import { onControlPlane } from "../src/db/migration-role.ts";
|
|
3
|
+
|
|
4
|
+
// Ghost accounts: anonymous self-serve API keys. `POST /v1/keys` with no auth
|
|
5
|
+
// mints an account with ghost=true and email NULL; a claim token (hash stored,
|
|
6
|
+
// raw returned once in the claim URL) later attaches an email via the magic-link
|
|
7
|
+
// flow. Email's NOT NULL is dropped; the existing plain UNIQUE constraint stays —
|
|
8
|
+
// Postgres unique constraints ignore NULLs (multiple NULL emails coexist), so
|
|
9
|
+
// `ON CONFLICT (email)` upserts keep working unchanged and no partial index is
|
|
10
|
+
// needed. Control-plane (TARGET).
|
|
11
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
12
|
+
await sql`SET lock_timeout = '30s'`.execute(db);
|
|
13
|
+
await onControlPlane(async () => {
|
|
14
|
+
await sql`
|
|
15
|
+
ALTER TABLE accounts
|
|
16
|
+
ADD COLUMN ghost BOOLEAN NOT NULL DEFAULT false
|
|
17
|
+
`.execute(db);
|
|
18
|
+
await sql`ALTER TABLE accounts ALTER COLUMN email DROP NOT NULL`.execute(
|
|
19
|
+
db,
|
|
20
|
+
);
|
|
21
|
+
await sql`
|
|
22
|
+
CREATE TABLE claim_tokens (
|
|
23
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
24
|
+
account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
|
|
25
|
+
token_hash TEXT NOT NULL UNIQUE,
|
|
26
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
27
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
28
|
+
used_at TIMESTAMPTZ
|
|
29
|
+
)
|
|
30
|
+
`.execute(db);
|
|
31
|
+
// Sweeper + claim flow look tokens up by account.
|
|
32
|
+
await sql`CREATE INDEX claim_tokens_account_id_idx ON claim_tokens (account_id)`.execute(
|
|
33
|
+
db,
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
39
|
+
await onControlPlane(async () => {
|
|
40
|
+
await sql`DROP TABLE IF EXISTS claim_tokens`.execute(db);
|
|
41
|
+
// Unclaimed ghosts have NULL emails — they cannot survive a NOT NULL
|
|
42
|
+
// restore, so drop them before reinstating the constraint.
|
|
43
|
+
await sql`DELETE FROM accounts WHERE email IS NULL`.execute(db);
|
|
44
|
+
await sql`ALTER TABLE accounts ALTER COLUMN email SET NOT NULL`.execute(db);
|
|
45
|
+
await sql`ALTER TABLE accounts DROP COLUMN IF EXISTS ghost`.execute(db);
|
|
46
|
+
});
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@secondlayer/shared",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.29.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -112,6 +112,10 @@
|
|
|
112
112
|
"types": "./dist/src/errors.d.ts",
|
|
113
113
|
"import": "./dist/src/errors.js"
|
|
114
114
|
},
|
|
115
|
+
"./x402": {
|
|
116
|
+
"types": "./dist/src/x402.d.ts",
|
|
117
|
+
"import": "./dist/src/x402.js"
|
|
118
|
+
},
|
|
115
119
|
"./crypto/secrets": {
|
|
116
120
|
"types": "./dist/src/crypto/secrets.d.ts",
|
|
117
121
|
"import": "./dist/src/crypto/secrets.js"
|
|
@@ -163,7 +167,7 @@
|
|
|
163
167
|
"prepublishOnly": "bun run build"
|
|
164
168
|
},
|
|
165
169
|
"dependencies": {
|
|
166
|
-
"@secondlayer/stacks": "^2.
|
|
170
|
+
"@secondlayer/stacks": "^2.5.0",
|
|
167
171
|
"kysely": "0.28.15",
|
|
168
172
|
"kysely-postgres-js": "3.0.0",
|
|
169
173
|
"postgres": "^3.4.6",
|