tapimo 0.0.2 → 0.1.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/README.md +11 -2
- package/dist/ApiKey.d.ts +12 -11
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +10 -12
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +139 -0
- package/dist/ApiKeys.d.ts.map +1 -0
- package/dist/ApiKeys.js +166 -0
- package/dist/ApiKeys.js.map +1 -0
- package/dist/App.d.ts +920 -910
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +36 -12
- package/dist/App.js.map +1 -1
- package/dist/Handler.d.ts +86 -0
- package/dist/Handler.d.ts.map +1 -0
- package/dist/Handler.js +83 -0
- package/dist/Handler.js.map +1 -0
- package/dist/Scope.d.ts +4 -1
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +5 -1
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.d.ts +3 -5
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +9 -2
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/Access.d.ts +1 -3
- package/dist/admin/Access.d.ts.map +1 -1
- package/dist/admin/Access.js +1 -3
- package/dist/admin/Access.js.map +1 -1
- package/dist/admin/App.d.ts +98 -209
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +2 -4
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +7 -5
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +8 -9
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/scopes.d.ts +3 -0
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +101 -215
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +17 -38
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +1 -1
- package/dist/apps/balances.d.ts +2 -2
- package/dist/apps/receipts.d.ts +43 -43
- package/dist/apps/tokens.d.ts +454 -454
- package/dist/apps/transactions.d.ts +43 -43
- package/dist/apps/transfers.d.ts +29 -29
- package/dist/apps/webhooks.d.ts +5 -2
- package/dist/apps/webhooks.d.ts.map +1 -1
- package/dist/apps/webhooks.js +38 -34
- package/dist/apps/webhooks.js.map +1 -1
- package/dist/{Cli.d.ts → cli/Cli.d.ts} +13 -2
- package/dist/cli/Cli.d.ts.map +1 -0
- package/dist/cli/Cli.js +19 -0
- package/dist/cli/Cli.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +4 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/admin.d.ts +15 -0
- package/dist/cli/commands/admin.d.ts.map +1 -0
- package/dist/cli/commands/admin.js +60 -0
- package/dist/cli/commands/admin.js.map +1 -0
- package/dist/cloudflare.d.ts +7 -0
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +9 -0
- package/dist/cloudflare.js.map +1 -1
- package/dist/db/Db.d.ts +103 -0
- package/dist/db/Db.d.ts.map +1 -0
- package/dist/db/Db.js +274 -0
- package/dist/db/Db.js.map +1 -0
- package/dist/db/Schema.d.ts +88 -0
- package/dist/db/Schema.d.ts.map +1 -0
- package/dist/db/Schema.js +130 -0
- package/dist/db/Schema.js.map +1 -0
- package/dist/db/tables/organizations.d.ts +79 -0
- package/dist/db/tables/organizations.d.ts.map +1 -0
- package/dist/db/tables/organizations.js +81 -0
- package/dist/db/tables/organizations.js.map +1 -0
- package/dist/db/tables/verifiedTokens.d.ts +53 -0
- package/dist/db/tables/verifiedTokens.d.ts.map +1 -0
- package/dist/db/tables/verifiedTokens.js +74 -0
- package/dist/db/tables/verifiedTokens.js.map +1 -0
- package/dist/db/tables/webhookDeliveries.d.ts +71 -0
- package/dist/db/tables/webhookDeliveries.d.ts.map +1 -0
- package/dist/db/tables/webhookDeliveries.js +119 -0
- package/dist/db/tables/webhookDeliveries.js.map +1 -0
- package/dist/db/tables/webhookSubscriptions.d.ts +158 -0
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -0
- package/dist/db/tables/webhookSubscriptions.js +272 -0
- package/dist/db/tables/webhookSubscriptions.js.map +1 -0
- package/dist/handlers/internal/executionError.d.ts +25 -0
- package/dist/handlers/internal/executionError.d.ts.map +1 -0
- package/dist/handlers/internal/executionError.js +184 -0
- package/dist/handlers/internal/executionError.js.map +1 -0
- package/dist/handlers/internal/multisig.d.ts +237 -0
- package/dist/handlers/internal/multisig.d.ts.map +1 -0
- package/dist/handlers/internal/multisig.js +567 -0
- package/dist/handlers/internal/multisig.js.map +1 -0
- package/dist/handlers/internal/requestListener.d.ts +124 -0
- package/dist/handlers/internal/requestListener.d.ts.map +1 -0
- package/dist/handlers/internal/requestListener.js +173 -0
- package/dist/handlers/internal/requestListener.js.map +1 -0
- package/dist/handlers/internal/sponsorship.d.ts +83 -0
- package/dist/handlers/internal/sponsorship.d.ts.map +1 -0
- package/dist/handlers/internal/sponsorship.js +103 -0
- package/dist/handlers/internal/sponsorship.js.map +1 -0
- package/dist/handlers/internal/types.d.ts +284 -0
- package/dist/handlers/internal/types.d.ts.map +1 -0
- package/dist/handlers/internal/types.js +2 -0
- package/dist/handlers/internal/types.js.map +1 -0
- package/dist/handlers/internal/utils.d.ts +34 -0
- package/dist/handlers/internal/utils.d.ts.map +1 -0
- package/dist/handlers/internal/utils.js +131 -0
- package/dist/handlers/internal/utils.js.map +1 -0
- package/dist/handlers/relay.d.ts +119 -0
- package/dist/handlers/relay.d.ts.map +1 -0
- package/dist/handlers/relay.js +1264 -0
- package/dist/handlers/relay.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/internal/Auth.d.ts +16 -10
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +72 -12
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/RpcSchema.d.ts +10 -0
- package/dist/internal/RpcSchema.d.ts.map +1 -0
- package/dist/internal/RpcSchema.js +2 -0
- package/dist/internal/RpcSchema.js.map +1 -0
- package/dist/internal/Store.d.ts +42 -3
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +65 -3
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/VerifiedTokens.d.ts +15 -34
- package/dist/internal/VerifiedTokens.d.ts.map +1 -1
- package/dist/internal/VerifiedTokens.js +115 -159
- package/dist/internal/VerifiedTokens.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +49 -35
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +92 -205
- package/dist/internal/Webhooks.js.map +1 -1
- package/package.json +7 -2
- package/src/ApiKey.test.ts +3 -3
- package/src/ApiKey.ts +10 -12
- package/src/ApiKeys.test.ts +175 -0
- package/src/ApiKeys.ts +205 -0
- package/src/App.test-d.ts +1 -1
- package/src/App.test.ts +10768 -351
- package/src/App.ts +79 -36
- package/src/Client.test-d.ts +1 -1
- package/src/Handler.ts +154 -0
- package/src/Scope.ts +5 -1
- package/src/Webhooks.test.ts +8 -7
- package/src/Webhooks.ts +11 -5
- package/src/admin/Access.ts +1 -3
- package/src/admin/App.ts +19 -24
- package/src/admin/apps/api-keys.test.ts +19 -18
- package/src/admin/apps/api-keys.ts +8 -9
- package/src/admin/apps/scopes.test.ts +4 -0
- package/src/admin/apps/verified-tokens.test.ts +3 -30
- package/src/admin/apps/verified-tokens.ts +17 -36
- package/src/admin/ui.generated.ts +1 -1
- package/src/apps/balances.test.ts +4 -3
- package/src/apps/blocks.test.ts +1 -1
- package/src/apps/exchanges.test.ts +1 -1
- package/src/apps/indexer.test.ts +1 -1
- package/src/apps/receipts.test.ts +1 -1
- package/src/apps/rpc.test.ts +100 -10
- package/src/apps/tokenlist.test.ts +5 -7
- package/src/apps/tokens.test.ts +4 -3
- package/src/apps/transactions.test.ts +1 -1
- package/src/apps/transfers.test.ts +1 -1
- package/src/apps/verified-tokens.test.ts +24 -12
- package/src/apps/webhooks.test.ts +130 -143
- package/src/apps/webhooks.ts +45 -47
- package/src/{Cli.test.ts → cli/Cli.test.ts} +10 -9
- package/src/{Cli.ts → cli/Cli.ts} +16 -9
- package/src/cli/bin.ts +4 -0
- package/src/cli/commands/admin.test.ts +71 -0
- package/src/cli/commands/admin.ts +60 -0
- package/src/cloudflare.ts +10 -0
- package/src/db/Db.test.ts +84 -0
- package/src/db/Db.ts +383 -0
- package/src/db/Schema.ts +164 -0
- package/src/db/tables/organizations.test.ts +124 -0
- package/src/db/tables/organizations.ts +127 -0
- package/src/db/tables/verifiedTokens.ts +111 -0
- package/src/db/tables/webhookDeliveries.ts +159 -0
- package/src/db/tables/webhookSubscriptions.ts +358 -0
- package/src/handlers/internal/executionError.ts +205 -0
- package/src/handlers/internal/multisig.localnet.test.ts +146 -0
- package/src/handlers/internal/multisig.test.ts +744 -0
- package/src/handlers/internal/multisig.ts +858 -0
- package/src/handlers/internal/relay.localnet.test.ts +2035 -0
- package/src/handlers/internal/requestListener.ts +273 -0
- package/src/handlers/internal/sponsorship.ts +186 -0
- package/src/handlers/internal/types.ts +378 -0
- package/src/handlers/internal/utils.ts +153 -0
- package/src/handlers/relay.ts +1605 -0
- package/src/index.ts +4 -2
- package/src/internal/Auth.test.ts +21 -21
- package/src/internal/Auth.ts +92 -19
- package/src/internal/RateLimit.test.ts +1 -1
- package/src/internal/RpcSchema.ts +10 -0
- package/src/internal/Store.test.ts +98 -10
- package/src/internal/Store.ts +112 -6
- package/src/internal/VerifiedTokens.test.ts +99 -115
- package/src/internal/VerifiedTokens.ts +123 -175
- package/src/internal/Webhooks.test.ts +107 -107
- package/src/internal/Webhooks.ts +102 -220
- package/dist/ApiKeySource.d.ts +0 -166
- package/dist/ApiKeySource.d.ts.map +0 -1
- package/dist/ApiKeySource.js +0 -234
- package/dist/ApiKeySource.js.map +0 -1
- package/dist/Cli.d.ts.map +0 -1
- package/dist/Cli.js +0 -13
- package/dist/Cli.js.map +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000000.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
- package/seeds/31318/verified-tokens.json +0 -30
- package/seeds/4217/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
- package/seeds/4217/icons/0x20c000000000000000000000048c8f36df1c9a4a.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000000520792dcccccccc.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000000a6da882d075a4c3.svg +0 -4
- package/seeds/4217/icons/0x20c000000000000000000000111111111e910f0f.svg +0 -30
- package/seeds/4217/icons/0x20c00000000000000000000014f22ca97301eb73.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000001621e21f71cf12fb.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000002f52d5cc21a3207b.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000003158081efd85bfc2.svg +0 -11
- package/seeds/4217/icons/0x20c0000000000000000000003554d28269e0f3c2.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000383a23bacb546ab9.svg +0 -1
- package/seeds/4217/icons/0x20c00000000000000000000042109aef2f8b28e1.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000005c0bac7cef389a11.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000006fd9a167923ba194.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000007f7ba549dd0251b9.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000008191667423f70e67.svg +0 -5
- package/seeds/4217/icons/0x20c0000000000000000000008ee4fcff88888888.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000009a4a4b17e0dc6651.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000ab02d39df30bd17e.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000ae247a1130450f09.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000aeed2ec36a54d0e5.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000b9537d11c60e8b50.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000bd95bfb69fbe6ce3.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000c412ec89d0c08be5.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000f047dd7018e50367.png +0 -0
- package/seeds/4217/verified-tokens.json +0 -177
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000009e8d7eb59b783726.svg +0 -1
- package/seeds/42431/icons/0x20c000000000000000000000d72572838bbee59c.svg +0 -1
- package/seeds/42431/verified-tokens.json +0 -44
- package/seeds/openrpc/README.md +0 -27
- package/seeds/openrpc/execution-apis.json +0 -8989
- package/src/ApiKeySource.test-d.ts +0 -11
- package/src/ApiKeySource.test.ts +0 -295
- package/src/ApiKeySource.ts +0 -303
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { Selectable } from 'kysely'
|
|
2
|
+
import { nanoid } from 'nanoid'
|
|
3
|
+
|
|
4
|
+
import type * as Db from '../Db.js'
|
|
5
|
+
import type * as db_Schema from '../Schema.js'
|
|
6
|
+
|
|
7
|
+
/** Columns of the `organizations` table, derived from `Schema.Organization`. */
|
|
8
|
+
export type Table = db_Schema.Organization
|
|
9
|
+
|
|
10
|
+
/** A stored organization row. */
|
|
11
|
+
export type Record = Selectable<Table>
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Inserts an organization and returns the stored record. The `id` defaults to
|
|
15
|
+
* a generated `org_…` handle when omitted.
|
|
16
|
+
*
|
|
17
|
+
* @param db - The database.
|
|
18
|
+
* @param input - The organization to insert.
|
|
19
|
+
* @returns The stored record.
|
|
20
|
+
*/
|
|
21
|
+
export function create(db: Db.Db, input: create.Input): Promise<Record> {
|
|
22
|
+
const now = new Date().toISOString()
|
|
23
|
+
return db.kysely
|
|
24
|
+
.insertInto('organizations')
|
|
25
|
+
.values({
|
|
26
|
+
createdAt: now,
|
|
27
|
+
createdBy: input.createdBy ?? null,
|
|
28
|
+
id: input.id ?? `org_${nanoid()}`,
|
|
29
|
+
name: input.name,
|
|
30
|
+
updatedAt: now,
|
|
31
|
+
})
|
|
32
|
+
.returningAll()
|
|
33
|
+
.executeTakeFirstOrThrow()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export declare namespace create {
|
|
37
|
+
/** Fields accepted when inserting an organization. */
|
|
38
|
+
type Input = {
|
|
39
|
+
/** Identity creating the organization (e.g. admin email), recorded for audit. */
|
|
40
|
+
createdBy?: string | undefined
|
|
41
|
+
/** Explicit id; a generated `org_…` handle is used when omitted. */
|
|
42
|
+
id?: string | undefined
|
|
43
|
+
/** Human-readable organization name. */
|
|
44
|
+
name: string
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Reads an organization by id.
|
|
50
|
+
*
|
|
51
|
+
* @param db - The database.
|
|
52
|
+
* @param id - The organization id (`org_…`).
|
|
53
|
+
* @returns The record, or `undefined` when absent.
|
|
54
|
+
*/
|
|
55
|
+
export function get(db: Db.Db, id: string): Promise<Record | undefined> {
|
|
56
|
+
return db.kysely.selectFrom('organizations').selectAll().where('id', '=', id).executeTakeFirst()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Lists organizations, newest first.
|
|
61
|
+
*
|
|
62
|
+
* @param db - The database.
|
|
63
|
+
* @returns The records.
|
|
64
|
+
*/
|
|
65
|
+
export function list(db: Db.Db): Promise<Record[]> {
|
|
66
|
+
return db.kysely.selectFrom('organizations').selectAll().orderBy('createdAt', 'desc').execute()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Renames an organization, bumping `updatedAt`.
|
|
71
|
+
*
|
|
72
|
+
* @param db - The database.
|
|
73
|
+
* @param id - The organization id (`org_…`).
|
|
74
|
+
* @param input - The fields to update.
|
|
75
|
+
* @returns The updated record, or `undefined` when absent.
|
|
76
|
+
*/
|
|
77
|
+
export function update(db: Db.Db, id: string, input: update.Input): Promise<Record | undefined> {
|
|
78
|
+
return db.kysely
|
|
79
|
+
.updateTable('organizations')
|
|
80
|
+
.set({ name: input.name, updatedAt: new Date().toISOString() })
|
|
81
|
+
.where('id', '=', id)
|
|
82
|
+
.returningAll()
|
|
83
|
+
.executeTakeFirst()
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export declare namespace update {
|
|
87
|
+
/** Mutable organization fields. */
|
|
88
|
+
type Input = {
|
|
89
|
+
/** New human-readable organization name. */
|
|
90
|
+
name: string
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Inserts an organization when absent (`ON CONFLICT DO NOTHING`) — the
|
|
96
|
+
* mint/backfill path, where a key's `orgId` must resolve to a real row. The
|
|
97
|
+
* `name` defaults to the id for degenerate orgs created by the mint fallback.
|
|
98
|
+
*
|
|
99
|
+
* @param db - The database.
|
|
100
|
+
* @param input - The organization to ensure.
|
|
101
|
+
*/
|
|
102
|
+
export async function upsert(db: Db.Db, input: upsert.Input): Promise<void> {
|
|
103
|
+
const now = new Date().toISOString()
|
|
104
|
+
await db.kysely
|
|
105
|
+
.insertInto('organizations')
|
|
106
|
+
.values({
|
|
107
|
+
createdAt: now,
|
|
108
|
+
createdBy: input.createdBy ?? null,
|
|
109
|
+
id: input.id,
|
|
110
|
+
name: input.name ?? input.id,
|
|
111
|
+
updatedAt: now,
|
|
112
|
+
})
|
|
113
|
+
.onConflict((oc) => oc.column('id').doNothing())
|
|
114
|
+
.execute()
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export declare namespace upsert {
|
|
118
|
+
/** Fields accepted when ensuring an organization exists. */
|
|
119
|
+
type Input = {
|
|
120
|
+
/** Identity creating the organization, recorded for audit. */
|
|
121
|
+
createdBy?: string | undefined
|
|
122
|
+
/** The organization id (`org_…`, or a mint-fallback key id). */
|
|
123
|
+
id: string
|
|
124
|
+
/** Human-readable organization name; defaults to the id. */
|
|
125
|
+
name?: string | undefined
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { Selectable } from 'kysely'
|
|
2
|
+
import type { Hex } from 'ox'
|
|
3
|
+
|
|
4
|
+
import type * as VerifiedTokens from '../../internal/VerifiedTokens.js'
|
|
5
|
+
import type * as Db from '../Db.js'
|
|
6
|
+
import type * as db_Schema from '../Schema.js'
|
|
7
|
+
|
|
8
|
+
/** Columns of the `verified_tokens` table, derived from `Schema.VerifiedToken`. */
|
|
9
|
+
export type Table = db_Schema.VerifiedToken
|
|
10
|
+
|
|
11
|
+
/** Columns of the `verified_token_lists` table, derived from `Schema.VerifiedTokenList`. */
|
|
12
|
+
export type ListTable = db_Schema.VerifiedTokenList
|
|
13
|
+
|
|
14
|
+
/** A stored verified-token row. */
|
|
15
|
+
export type Row = Selectable<Table>
|
|
16
|
+
|
|
17
|
+
/** A chain's list-level metadata. */
|
|
18
|
+
export type Meta = Selectable<ListTable>
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Reads a chain's list metadata — the "head" the soft-refresh cache compares
|
|
22
|
+
* versions against.
|
|
23
|
+
*
|
|
24
|
+
* @param db - The database.
|
|
25
|
+
* @param chainId - The chain id.
|
|
26
|
+
* @returns The metadata, or `undefined` when the chain has no list yet.
|
|
27
|
+
*/
|
|
28
|
+
export function head(db: Db.Db, chainId: number): Promise<Meta | undefined> {
|
|
29
|
+
return db.kysely
|
|
30
|
+
.selectFrom('verified_token_lists')
|
|
31
|
+
.selectAll()
|
|
32
|
+
.where('chainId', '=', chainId)
|
|
33
|
+
.executeTakeFirst()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Reads a chain's tokens in canonical list order.
|
|
38
|
+
*
|
|
39
|
+
* @param db - The database.
|
|
40
|
+
* @param chainId - The chain id.
|
|
41
|
+
* @returns The rows.
|
|
42
|
+
*/
|
|
43
|
+
export function list(db: Db.Db, chainId: number): Promise<Row[]> {
|
|
44
|
+
return db.kysely
|
|
45
|
+
.selectFrom('verified_tokens')
|
|
46
|
+
.selectAll()
|
|
47
|
+
.where('chainId', '=', chainId)
|
|
48
|
+
.orderBy('position')
|
|
49
|
+
.execute()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Publishes a chain's whole list: replaces its token rows (positions rewritten
|
|
54
|
+
* wholesale) and bumps the list metadata. Callers run this inside the
|
|
55
|
+
* per-chain publish lock/transaction, so the rewrite is atomic.
|
|
56
|
+
*
|
|
57
|
+
* @param db - The database (a transaction-scoped handle).
|
|
58
|
+
* @param chainId - The chain id.
|
|
59
|
+
* @param input - The validated list and its new version metadata.
|
|
60
|
+
*/
|
|
61
|
+
export async function publish(db: Db.Db, chainId: number, input: publish.Input): Promise<void> {
|
|
62
|
+
await db.kysely.deleteFrom('verified_tokens').where('chainId', '=', chainId).execute()
|
|
63
|
+
if (input.tokens.length > 0)
|
|
64
|
+
await db.kysely
|
|
65
|
+
.insertInto('verified_tokens')
|
|
66
|
+
.values(
|
|
67
|
+
input.tokens.map((token, position) => ({
|
|
68
|
+
address: token.address,
|
|
69
|
+
chainId,
|
|
70
|
+
currency: token.currency,
|
|
71
|
+
decimals: token.decimals,
|
|
72
|
+
logoUri: token.logoUri ?? null,
|
|
73
|
+
name: token.name,
|
|
74
|
+
position,
|
|
75
|
+
symbol: token.symbol,
|
|
76
|
+
})),
|
|
77
|
+
)
|
|
78
|
+
.execute()
|
|
79
|
+
await db.kysely
|
|
80
|
+
.insertInto('verified_token_lists')
|
|
81
|
+
.values({ chainId, updatedAt: input.updatedAt, version: input.version })
|
|
82
|
+
.onConflict((oc) =>
|
|
83
|
+
oc.column('chainId').doUpdateSet({ updatedAt: input.updatedAt, version: input.version }),
|
|
84
|
+
)
|
|
85
|
+
.execute()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export declare namespace publish {
|
|
89
|
+
/** A validated list to publish. */
|
|
90
|
+
type Input = {
|
|
91
|
+
/** Tokens in canonical order (addresses lowercased by the domain layer). */
|
|
92
|
+
tokens: readonly VerifiedTokens.Token[]
|
|
93
|
+
/** ISO timestamp of the publish. */
|
|
94
|
+
updatedAt: string
|
|
95
|
+
/** New opaque list version. */
|
|
96
|
+
version: string
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Maps a stored row to the domain token (null `logoUri` → absent field). */
|
|
101
|
+
export function toToken(row: Row): VerifiedTokens.Token {
|
|
102
|
+
return {
|
|
103
|
+
address: row.address as Hex.Hex,
|
|
104
|
+
currency: row.currency,
|
|
105
|
+
decimals: row.decimals,
|
|
106
|
+
id: row.address as Hex.Hex,
|
|
107
|
+
name: row.name,
|
|
108
|
+
symbol: row.symbol,
|
|
109
|
+
...(row.logoUri === null ? {} : { logoUri: row.logoUri }),
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { Selectable } from 'kysely'
|
|
2
|
+
|
|
3
|
+
import type * as Webhooks from '../../internal/Webhooks.js'
|
|
4
|
+
import type * as Db from '../Db.js'
|
|
5
|
+
import type * as db_Schema from '../Schema.js'
|
|
6
|
+
|
|
7
|
+
/** Columns of the `webhook_deliveries` table, derived from `Schema.WebhookDelivery`. */
|
|
8
|
+
export type Table = db_Schema.WebhookDelivery
|
|
9
|
+
|
|
10
|
+
/** A stored webhook-delivery row. */
|
|
11
|
+
export type Record = Selectable<Table>
|
|
12
|
+
|
|
13
|
+
/** Maps a stored row to the domain delivery (null columns → absent fields). */
|
|
14
|
+
export function toDelivery(row: Record): Webhooks.Delivery {
|
|
15
|
+
return {
|
|
16
|
+
attempt: row.attempt,
|
|
17
|
+
createdAt: row.createdAt,
|
|
18
|
+
envelope: row.envelope,
|
|
19
|
+
...(row.error === null ? {} : { error: row.error }),
|
|
20
|
+
eventId: row.eventId,
|
|
21
|
+
id: row.id,
|
|
22
|
+
requestUrl: row.requestUrl,
|
|
23
|
+
...(row.responseMs === null ? {} : { responseMs: row.responseMs }),
|
|
24
|
+
...(row.responseStatus === null ? {} : { responseStatus: row.responseStatus }),
|
|
25
|
+
status: row.status,
|
|
26
|
+
subscriptionId: row.subscriptionId,
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Inserts a delivery row from its domain value.
|
|
32
|
+
*
|
|
33
|
+
* @param db - The database.
|
|
34
|
+
* @param delivery - The delivery to insert.
|
|
35
|
+
* @param expiresAt - Retention deadline (ISO); the row is invisible past it.
|
|
36
|
+
*/
|
|
37
|
+
export async function insert(
|
|
38
|
+
db: Db.Db,
|
|
39
|
+
delivery: Webhooks.Delivery,
|
|
40
|
+
expiresAt: string,
|
|
41
|
+
): Promise<void> {
|
|
42
|
+
await db.kysely
|
|
43
|
+
.insertInto('webhook_deliveries')
|
|
44
|
+
.values({
|
|
45
|
+
attempt: delivery.attempt,
|
|
46
|
+
createdAt: delivery.createdAt,
|
|
47
|
+
envelope: delivery.envelope,
|
|
48
|
+
error: delivery.error ?? null,
|
|
49
|
+
eventId: delivery.eventId,
|
|
50
|
+
expiresAt,
|
|
51
|
+
id: delivery.id,
|
|
52
|
+
requestUrl: delivery.requestUrl,
|
|
53
|
+
responseMs: delivery.responseMs ?? null,
|
|
54
|
+
responseStatus: delivery.responseStatus ?? null,
|
|
55
|
+
status: delivery.status,
|
|
56
|
+
subscriptionId: delivery.subscriptionId,
|
|
57
|
+
})
|
|
58
|
+
.execute()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Lists a subscription's unexpired deliveries, newest first, with keyset
|
|
63
|
+
* paging (`id < cursor` — ids embed a zero-padded timestamp, so lexical order
|
|
64
|
+
* is chronological).
|
|
65
|
+
*
|
|
66
|
+
* @param db - The database.
|
|
67
|
+
* @param subscriptionId - The owning subscription id (`wh_…`).
|
|
68
|
+
* @param options - Paging options plus the retention timestamp.
|
|
69
|
+
* @returns The deliveries.
|
|
70
|
+
*/
|
|
71
|
+
export async function list(
|
|
72
|
+
db: Db.Db,
|
|
73
|
+
subscriptionId: string,
|
|
74
|
+
options: list.Options,
|
|
75
|
+
): Promise<Webhooks.Delivery[]> {
|
|
76
|
+
let query = db.kysely
|
|
77
|
+
.selectFrom('webhook_deliveries')
|
|
78
|
+
.selectAll()
|
|
79
|
+
.where('subscriptionId', '=', subscriptionId)
|
|
80
|
+
.where('expiresAt', '>', options.now)
|
|
81
|
+
.orderBy('id', 'desc')
|
|
82
|
+
if (options.cursor) query = query.where('id', '<', options.cursor)
|
|
83
|
+
if (options.offset) query = query.offset(options.offset)
|
|
84
|
+
if (options.limit !== undefined) query = query.limit(options.limit)
|
|
85
|
+
return (await query.execute()).map(toDelivery)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export declare namespace list {
|
|
89
|
+
/** Options for {@link list}. */
|
|
90
|
+
type Options = {
|
|
91
|
+
/** Return deliveries whose id sorts before this one (older entries). */
|
|
92
|
+
cursor?: string | undefined
|
|
93
|
+
/** Maximum deliveries to return. */
|
|
94
|
+
limit?: number | undefined
|
|
95
|
+
/** ISO timestamp retention is evaluated against. */
|
|
96
|
+
now: string
|
|
97
|
+
/** Rows to skip from the head (positional pagination; exclusive with `cursor`). */
|
|
98
|
+
offset?: number | undefined
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Counts a subscription's unexpired deliveries.
|
|
104
|
+
*
|
|
105
|
+
* @param db - The database.
|
|
106
|
+
* @param subscriptionId - The owning subscription id (`wh_…`).
|
|
107
|
+
* @param now - ISO timestamp retention is evaluated against.
|
|
108
|
+
* @returns The count.
|
|
109
|
+
*/
|
|
110
|
+
export async function count(db: Db.Db, subscriptionId: string, now: string): Promise<number> {
|
|
111
|
+
const row = await db.kysely
|
|
112
|
+
.selectFrom('webhook_deliveries')
|
|
113
|
+
.select((eb) => eb.fn.countAll().as('count'))
|
|
114
|
+
.where('subscriptionId', '=', subscriptionId)
|
|
115
|
+
.where('expiresAt', '>', now)
|
|
116
|
+
.executeTakeFirstOrThrow()
|
|
117
|
+
return Number(row.count)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Reads a single unexpired delivery scoped to its subscription.
|
|
122
|
+
*
|
|
123
|
+
* @param db - The database.
|
|
124
|
+
* @param subscriptionId - The owning subscription id (`wh_…`).
|
|
125
|
+
* @param deliveryId - The delivery id (`whd_…`).
|
|
126
|
+
* @param now - ISO timestamp retention is evaluated against.
|
|
127
|
+
* @returns The delivery, or `null` when absent.
|
|
128
|
+
*/
|
|
129
|
+
export async function get(
|
|
130
|
+
db: Db.Db,
|
|
131
|
+
subscriptionId: string,
|
|
132
|
+
deliveryId: string,
|
|
133
|
+
now: string,
|
|
134
|
+
): Promise<Webhooks.Delivery | null> {
|
|
135
|
+
const row = await db.kysely
|
|
136
|
+
.selectFrom('webhook_deliveries')
|
|
137
|
+
.selectAll()
|
|
138
|
+
.where('subscriptionId', '=', subscriptionId)
|
|
139
|
+
.where('id', '=', deliveryId)
|
|
140
|
+
.where('expiresAt', '>', now)
|
|
141
|
+
.executeTakeFirst()
|
|
142
|
+
return row ? toDelivery(row) : null
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Deletes deliveries past their retention deadline. Called best-effort from
|
|
147
|
+
* the poller tick.
|
|
148
|
+
*
|
|
149
|
+
* @param db - The database.
|
|
150
|
+
* @param now - ISO timestamp retention is evaluated against.
|
|
151
|
+
* @returns The number of rows deleted.
|
|
152
|
+
*/
|
|
153
|
+
export async function pruneExpired(db: Db.Db, now: string): Promise<number> {
|
|
154
|
+
const result = await db.kysely
|
|
155
|
+
.deleteFrom('webhook_deliveries')
|
|
156
|
+
.where('expiresAt', '<=', now)
|
|
157
|
+
.executeTakeFirst()
|
|
158
|
+
return Number(result.numDeletedRows)
|
|
159
|
+
}
|