@arkiv-network/sdk 0.8.1-dev.1 → 0.9.0-next.2
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 +180 -61
- package/dist/chains/index.d.ts +17 -17
- package/dist/changeOwnership-Cy9gfyjN.d.cts +1160 -0
- package/dist/changeOwnership-Cy9gfyjN.d.cts.map +1 -0
- package/dist/changeOwnership-gXf-lBqI.d.ts +1160 -0
- package/dist/changeOwnership-gXf-lBqI.d.ts.map +1 -0
- package/dist/entity/index.cjs +4 -10
- package/dist/entity/index.d.cts +3 -3
- package/dist/entity/index.d.ts +3 -3
- package/dist/entity/index.js +3 -4
- package/dist/entity-BM1unrQf.cjs +41 -0
- package/dist/{entity-DJ0Gml9c.cjs → entity-BgaFJSaV.cjs} +4 -4
- package/dist/entity-CFAI1KyG.js +36 -0
- package/dist/entity-CFAI1KyG.js.map +1 -0
- package/dist/{entity-CniBgBSd.js → entity-CGqx_AU0.js} +4 -4
- package/dist/entity-CGqx_AU0.js.map +1 -0
- package/dist/{payload-AfUfSctb.d.ts → expirationTime-C7PZK49K.d.ts} +8 -37
- package/dist/expirationTime-C7PZK49K.d.ts.map +1 -0
- package/dist/expirationTime-CkIGNAg8.cjs +140 -0
- package/dist/{payload-D167BlJR.d.cts → expirationTime-DOB8V4B8.d.cts} +8 -37
- package/dist/expirationTime-DOB8V4B8.d.cts.map +1 -0
- package/dist/{expiry-Cgdb_dbq.js → expirationTime-UKPuA-LM.js} +62 -27
- package/dist/expirationTime-UKPuA-LM.js.map +1 -0
- package/dist/expiry-B48I-yTA.d.cts +40 -0
- package/dist/expiry-B48I-yTA.d.cts.map +1 -0
- package/dist/expiry-S2PUL8Hg.d.ts +40 -0
- package/dist/expiry-S2PUL8Hg.d.ts.map +1 -0
- package/dist/index-C-mMF5WZ.d.cts +735 -0
- package/dist/index-C-mMF5WZ.d.cts.map +1 -0
- package/dist/{index-BkqSnGJH.d.ts → index-C4zZqJ9S.d.ts} +5 -27
- package/dist/index-C4zZqJ9S.d.ts.map +1 -0
- package/dist/{index-CLhsFyVH.d.cts → index-CcVWYB6v.d.cts} +5 -27
- package/dist/index-CcVWYB6v.d.cts.map +1 -0
- package/dist/index-DCx2XC6S.d.ts +489 -0
- package/dist/index-DCx2XC6S.d.ts.map +1 -0
- package/dist/index-DLb7BfIw.d.ts +735 -0
- package/dist/index-DLb7BfIw.d.ts.map +1 -0
- package/dist/index-DzriOUm8.d.cts +489 -0
- package/dist/index-DzriOUm8.d.cts.map +1 -0
- package/dist/index.cjs +162 -146
- package/dist/index.d.cts +180 -133
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +180 -133
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +93 -83
- package/dist/index.js.map +1 -1
- package/dist/params-BuIrJA9a.cjs +45 -0
- package/dist/params-DDJOnsNi.js +22 -0
- package/dist/params-DDJOnsNi.js.map +1 -0
- package/dist/query/index.cjs +9 -4
- package/dist/query/index.d.cts +6 -6
- package/dist/query/index.d.ts +6 -6
- package/dist/query/index.js +4 -5
- package/dist/query-D0KtuFh2.cjs +1625 -0
- package/dist/query-DpRDozmj.js +1417 -0
- package/dist/query-DpRDozmj.js.map +1 -0
- package/dist/schema/index.cjs +46 -0
- package/dist/schema/index.d.cts +2 -0
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +3 -0
- package/dist/{attr-BXTkpnoc.cjs → schema-B9AyXcgU.cjs} +513 -246
- package/dist/{attr-tmyREHtw.js → schema-DY4sqehl.js} +427 -244
- package/dist/schema-DY4sqehl.js.map +1 -0
- package/dist/types/index.cjs +1 -1
- package/dist/types/index.d.cts +5 -5
- package/dist/types/index.d.ts +5 -5
- package/dist/types/index.js +1 -1
- package/dist/utils/index.cjs +3 -5
- package/dist/utils/index.d.cts +3 -3
- package/dist/utils/index.d.ts +3 -3
- package/dist/utils/index.js +3 -3
- package/package.json +9 -12
- package/src/actions/public/getEntity.test.ts +69 -0
- package/src/actions/public/getEntity.ts +34 -20
- package/src/actions/public/predictEntityKeys.ts +8 -7
- package/src/actions/public/query.test.ts +58 -0
- package/src/actions/public/query.ts +41 -13
- package/src/actions/wallet/createEntity.ts +34 -63
- package/src/actions/wallet/executeBatch.test.ts +38 -0
- package/src/actions/wallet/executeBatch.ts +26 -9
- package/src/actions/wallet/extendEntity.ts +9 -8
- package/src/actions/wallet/patchEntity.ts +43 -52
- package/src/clients/createPublicClient.test.ts +10 -2
- package/src/clients/createWalletClient.ts +4 -1
- package/src/clients/decorators/arkivPublic.ts +123 -80
- package/src/clients/decorators/arkivWallet.ts +113 -65
- package/src/entity/create.test.ts +25 -21
- package/src/entity/expiry.ts +8 -6
- package/src/entity/flags.ts +1 -1
- package/src/entity/index.ts +2 -4
- package/src/entity/key.ts +3 -3
- package/src/entity/operations.ts +1 -1
- package/src/errors.ts +2 -11
- package/src/index.ts +18 -6
- package/src/query/builderBase.ts +166 -0
- package/src/query/countBuilder.test.ts +91 -0
- package/src/query/countBuilder.ts +67 -0
- package/src/query/engine.ts +9 -3
- package/src/query/errors.ts +24 -14
- package/src/query/expression.test.ts +129 -21
- package/src/query/expression.ts +323 -94
- package/src/query/index.ts +26 -4
- package/src/query/injection.test.ts +5 -11
- package/src/query/queryBuilder.test.ts +467 -58
- package/src/query/queryBuilder.ts +191 -98
- package/src/query/queryResult.ts +35 -9
- package/src/query/selection.test.ts +278 -24
- package/src/query/selection.ts +427 -86
- package/src/schema/attributes.test.ts +266 -0
- package/src/schema/attributes.ts +212 -0
- package/src/{attr → schema}/codec.test.ts +37 -5
- package/src/{attr → schema}/codec.ts +40 -11
- package/src/schema/column.ts +193 -0
- package/src/{attr → schema}/errors.ts +67 -10
- package/src/schema/index.ts +76 -0
- package/src/{attr → schema}/names.ts +4 -2
- package/src/schema/schema.test.ts +171 -0
- package/src/schema/schema.ts +250 -0
- package/src/{attr → schema}/types.ts +36 -30
- package/src/{attr → schema}/values.test.ts +62 -3
- package/src/{attr → schema}/values.ts +246 -65
- package/src/types/entity.test.ts +1 -44
- package/src/types/entity.ts +9 -55
- package/src/types/events.ts +1 -1
- package/src/types/index.ts +11 -4
- package/src/types/rpcSchema.ts +22 -16
- package/src/utils/arkivTransactions.test.ts +356 -116
- package/src/utils/arkivTransactions.ts +30 -38
- package/src/utils/entities.ts +10 -9
- package/src/utils/expirationTime.ts +5 -5
- package/src/utils/index.ts +0 -1
- package/src/utils/logger.test.ts +45 -0
- package/src/utils/logger.ts +5 -39
- package/src/utils/revert.test.ts +25 -0
- package/src/utils/revert.ts +28 -3
- package/dist/attr/index.cjs +0 -34
- package/dist/attr/index.d.cts +0 -2
- package/dist/attr/index.d.ts +0 -2
- package/dist/attr/index.js +0 -3
- package/dist/attr-tmyREHtw.js.map +0 -1
- package/dist/entity-B0t6sN7F.cjs +0 -71
- package/dist/entity-BIp_df9u.js +0 -67
- package/dist/entity-BIp_df9u.js.map +0 -1
- package/dist/entity-CniBgBSd.js.map +0 -1
- package/dist/expiry-BxOlvVWC.d.ts +0 -79
- package/dist/expiry-BxOlvVWC.d.ts.map +0 -1
- package/dist/expiry-CG9GhVXv.cjs +0 -135
- package/dist/expiry-Cgdb_dbq.js.map +0 -1
- package/dist/expiry-DRV29F1r.d.cts +0 -79
- package/dist/expiry-DRV29F1r.d.cts.map +0 -1
- package/dist/flags-DCD26uhe.cjs +0 -43
- package/dist/flags-DUT2gHEU.js +0 -33
- package/dist/flags-DUT2gHEU.js.map +0 -1
- package/dist/index-BkqSnGJH.d.ts.map +0 -1
- package/dist/index-C7fbakoI.d.cts +0 -278
- package/dist/index-C7fbakoI.d.cts.map +0 -1
- package/dist/index-CIcHPx2j.d.cts +0 -424
- package/dist/index-CIcHPx2j.d.cts.map +0 -1
- package/dist/index-CLhsFyVH.d.cts.map +0 -1
- package/dist/index-Cd2aaWme.d.ts +0 -424
- package/dist/index-Cd2aaWme.d.ts.map +0 -1
- package/dist/index-Cq6fa8AI.d.ts +0 -278
- package/dist/index-Cq6fa8AI.d.ts.map +0 -1
- package/dist/index-DaNeJUw8.d.ts +0 -955
- package/dist/index-DaNeJUw8.d.ts.map +0 -1
- package/dist/index-Dv16LO2s.d.cts +0 -955
- package/dist/index-Dv16LO2s.d.cts.map +0 -1
- package/dist/payload-AfUfSctb.d.ts.map +0 -1
- package/dist/payload-D167BlJR.d.cts.map +0 -1
- package/dist/payload-DE7wMztL.js +0 -92
- package/dist/payload-DE7wMztL.js.map +0 -1
- package/dist/payload-DqFweqiO.cjs +0 -108
- package/dist/query-9oojUdM7.cjs +0 -1128
- package/dist/query-Ber-lOJQ.js +0 -968
- package/dist/query-Ber-lOJQ.js.map +0 -1
- package/src/actions/public/getEntityCount.ts +0 -10
- package/src/attr/attributes.test.ts +0 -120
- package/src/attr/attributes.ts +0 -196
- package/src/attr/index.ts +0 -50
- package/src/types/mimeTypes.ts +0 -27
- package/src/utils/compression.test.ts +0 -32
- package/src/utils/compression.ts +0 -102
- package/src/utils/payload.ts +0 -36
- /package/src/{attr → schema}/decimal.ts +0 -0
|
@@ -13,8 +13,6 @@ import type { CreateEntityParameters } from "../actions/wallet/createEntity"
|
|
|
13
13
|
import type { DeleteEntityParameters } from "../actions/wallet/deleteEntity"
|
|
14
14
|
import type { ExtendEntityParameters } from "../actions/wallet/extendEntity"
|
|
15
15
|
import type { PatchEntityParameters } from "../actions/wallet/patchEntity"
|
|
16
|
-
// Internal seam: the ABI encoders are not part of the package's public surface.
|
|
17
|
-
import { encodeAttributes, encodeMutations } from "../attr/attributes"
|
|
18
16
|
import type { ArkivClient } from "../clients/baseClient"
|
|
19
17
|
import type { WalletArkivClient } from "../clients/createWalletClient"
|
|
20
18
|
import { ARKIV_ADDRESS } from "../consts"
|
|
@@ -31,7 +29,9 @@ import {
|
|
|
31
29
|
patchOperation,
|
|
32
30
|
transferOwnershipOperation,
|
|
33
31
|
} from "../entity/operations"
|
|
34
|
-
import { EmptyPatchError, EntityMutationError
|
|
32
|
+
import { EmptyPatchError, EntityMutationError } from "../errors"
|
|
33
|
+
// Internal seam: the ABI encoders are not part of the package's public surface.
|
|
34
|
+
import { encodeCreate, encodePatch } from "../schema/attributes"
|
|
35
35
|
import type { TxParams } from "../types"
|
|
36
36
|
|
|
37
37
|
import { getLogger } from "./logger"
|
|
@@ -39,16 +39,7 @@ import { describeEntityRevert } from "./revert"
|
|
|
39
39
|
|
|
40
40
|
const logger = getLogger("utils:arkiv-transactions")
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
const MIME_REGEX = /^[a-z][a-z0-9!#$&\-^_]*\/[a-z0-9][a-z0-9!#$&\-^_.+]*$/
|
|
44
|
-
|
|
45
|
-
function validateContentType(contentType: string): void {
|
|
46
|
-
if (!MIME_REGEX.test(contentType)) {
|
|
47
|
-
throw new InvalidContentTypeError(contentType)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export const ENTITY_ERRORS_ABI = parseAbi([
|
|
42
|
+
const ENTITY_ERRORS_ABI = parseAbi([
|
|
52
43
|
// Batch and operation framing.
|
|
53
44
|
"error EmptyBatch()",
|
|
54
45
|
"error InvalidOpType(uint8 operation)",
|
|
@@ -70,8 +61,8 @@ export const ENTITY_ERRORS_ABI = parseAbi([
|
|
|
70
61
|
"error NotOwner(bytes32 entityKey, address caller, address owner)",
|
|
71
62
|
"error ReadOnlyEntity(bytes32 entityKey)",
|
|
72
63
|
"error ReservedCreationFlags(uint8 creationFlags)",
|
|
73
|
-
// Expiry. The engine bounds an expiry only by the width of the field
|
|
74
|
-
//
|
|
64
|
+
// Expiry. The engine bounds an expiry only by the uint64 width of the field — the SDK's
|
|
65
|
+
// MAX_EXPIRES_AT — and by liveness. There is no separate cap on lifetime, so no error for one.
|
|
75
66
|
"error ExpiryDeadOnArrival(uint64 target, uint64 currentBlock)",
|
|
76
67
|
"error ExpiryNotExtended(bytes32 entityKey, uint64 newExpiresAt, uint64 currentExpiresAt)",
|
|
77
68
|
// Ownership transfer.
|
|
@@ -94,11 +85,11 @@ export type SendArkivTransactionResult = {
|
|
|
94
85
|
export async function sendArkivTransaction(
|
|
95
86
|
client: ArkivClient,
|
|
96
87
|
ops: {
|
|
97
|
-
creates?: CreateEntityParameters[]
|
|
98
|
-
patches?: PatchEntityParameters[]
|
|
99
|
-
deletes?: DeleteEntityParameters[]
|
|
100
|
-
extensions?: ExtendEntityParameters[]
|
|
101
|
-
ownershipChanges?: ChangeOwnershipParameters[]
|
|
88
|
+
creates?: readonly CreateEntityParameters[] | undefined
|
|
89
|
+
patches?: readonly PatchEntityParameters[] | undefined
|
|
90
|
+
deletes?: readonly DeleteEntityParameters[] | undefined
|
|
91
|
+
extensions?: readonly ExtendEntityParameters[] | undefined
|
|
92
|
+
ownershipChanges?: readonly ChangeOwnershipParameters[] | undefined
|
|
102
93
|
},
|
|
103
94
|
txParams?: TxParams,
|
|
104
95
|
): Promise<SendArkivTransactionResult> {
|
|
@@ -108,6 +99,21 @@ export async function sendArkivTransaction(
|
|
|
108
99
|
|
|
109
100
|
const { creates, patches, deletes, extensions, ownershipChanges } = ops
|
|
110
101
|
|
|
102
|
+
// Every write is checked against its schema before the block read, so one that does not fit
|
|
103
|
+
// fails without touching the network — and a network failure cannot mask it.
|
|
104
|
+
const encodedCreates = (creates ?? []).map((item) => ({
|
|
105
|
+
item,
|
|
106
|
+
attributes: encodeCreate(item.schema, item.values),
|
|
107
|
+
}))
|
|
108
|
+
|
|
109
|
+
const patchOps = (patches ?? []).map((item) => {
|
|
110
|
+
const mutations = encodePatch(item.schema, item)
|
|
111
|
+
if (mutations.length === 0) {
|
|
112
|
+
throw new EmptyPatchError(item.entityKey)
|
|
113
|
+
}
|
|
114
|
+
return patchOperation({ entityKey: item.entityKey, mutations })
|
|
115
|
+
})
|
|
116
|
+
|
|
111
117
|
// The block height, to resolve any relative expiry — which both creates and extensions carry.
|
|
112
118
|
// Skipped entirely for a batch with neither.
|
|
113
119
|
const currentBlock =
|
|
@@ -115,37 +121,23 @@ export async function sendArkivTransaction(
|
|
|
115
121
|
|
|
116
122
|
const expiryContext = { currentBlock }
|
|
117
123
|
|
|
118
|
-
const createOps =
|
|
119
|
-
validateContentType(item.contentType)
|
|
120
|
-
|
|
124
|
+
const createOps = encodedCreates.map(({ item, attributes }) => {
|
|
121
125
|
const salt = item.salt === undefined ? randomSalt() : resolveSalt(item.salt)
|
|
122
|
-
const expiry = resolveExpiry(item.
|
|
126
|
+
const expiry = resolveExpiry(item.expiration, expiryContext)
|
|
123
127
|
|
|
124
128
|
return createOperation({
|
|
125
129
|
salt,
|
|
126
130
|
expiry,
|
|
127
131
|
creationFlags: encodeCreationFlags(item.flags),
|
|
128
|
-
attributes
|
|
129
|
-
payload: item.payload,
|
|
130
|
-
contentType: item.contentType,
|
|
131
|
-
}),
|
|
132
|
+
attributes,
|
|
132
133
|
})
|
|
133
134
|
})
|
|
134
135
|
|
|
135
|
-
const patchOps = (patches ?? []).map((item) => {
|
|
136
|
-
if (item.contentType !== undefined) validateContentType(item.contentType)
|
|
137
|
-
const mutations = encodeMutations(item)
|
|
138
|
-
if (mutations.length === 0) {
|
|
139
|
-
throw new EmptyPatchError(item.entityKey)
|
|
140
|
-
}
|
|
141
|
-
return patchOperation({ entityKey: item.entityKey, mutations })
|
|
142
|
-
})
|
|
143
|
-
|
|
144
136
|
// An extension resolves its expiry exactly as a create does — the engine applies the same
|
|
145
137
|
// `max(expiresAt, currentBlock + minLifetime)` to both — so the same bounds are checked here
|
|
146
138
|
// rather than left to a revert.
|
|
147
139
|
const extendOps = (extensions ?? []).map((item) => {
|
|
148
|
-
const expiry = resolveExpiry(item.
|
|
140
|
+
const expiry = resolveExpiry(item.expiration, expiryContext)
|
|
149
141
|
return extendExpiryOperation({ entityKey: item.entityKey, expiry })
|
|
150
142
|
})
|
|
151
143
|
|
package/src/utils/entities.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { checksumAddress, type Hex
|
|
2
|
-
import type { AttributeSchema, Attributes } from "../attr"
|
|
3
|
-
// Internal seam: the JSON-RPC decoder is not part of the package's public surface.
|
|
4
|
-
import { asTypeTag, decodeRpcValue } from "../attr/codec"
|
|
1
|
+
import { checksumAddress, type Hex } from "viem"
|
|
5
2
|
import {
|
|
6
3
|
decodeCreationFlags,
|
|
7
4
|
encodeCreationFlags,
|
|
8
5
|
type ResolvedCreationFlags,
|
|
9
6
|
} from "../entity/flags"
|
|
7
|
+
import type { AttributeSchema, Attributes } from "../schema"
|
|
8
|
+
// Internal seam: the JSON-RPC decoder is not part of the package's public surface.
|
|
9
|
+
import { asTypeTag, decodeRpcValue } from "../schema/codec"
|
|
10
10
|
import { Entity, type EntityFields } from "../types/entity"
|
|
11
11
|
import type { RpcEntity } from "../types/rpcSchema"
|
|
12
12
|
import { getLogger } from "./logger"
|
|
@@ -29,9 +29,12 @@ function decodeAttributes(rpcAttributes: NonNullable<RpcEntity["attributes"]>):
|
|
|
29
29
|
|
|
30
30
|
/** The same, for the values-free `attributeSchema` projection. */
|
|
31
31
|
function decodeSchema(entries: NonNullable<RpcEntity["attributeSchema"]>): AttributeSchema {
|
|
32
|
-
const schema: Record<string,
|
|
33
|
-
for (const { name, type } of entries) {
|
|
34
|
-
schema[name] =
|
|
32
|
+
const schema: Record<string, AttributeSchema[string]> = {}
|
|
33
|
+
for (const { name, type, indexed } of entries) {
|
|
34
|
+
schema[name] = {
|
|
35
|
+
type: asTypeTag(type),
|
|
36
|
+
indexed: typeof indexed === "boolean" ? indexed : undefined,
|
|
37
|
+
}
|
|
35
38
|
}
|
|
36
39
|
return schema
|
|
37
40
|
}
|
|
@@ -53,8 +56,6 @@ export function entityFromRpcResult(rpcEntity: RpcEntity): Entity {
|
|
|
53
56
|
updatedAt: toBlock(rpcEntity.updatedAt),
|
|
54
57
|
expiresAt: toBlock(rpcEntity.expiresAt),
|
|
55
58
|
creationFlags: decodeFlags(rpcEntity.creationFlags),
|
|
56
|
-
contentType: rpcEntity.contentType,
|
|
57
|
-
payload: rpcEntity.payload !== undefined ? hexToBytes(rpcEntity.payload) : undefined,
|
|
58
59
|
attributeSchema:
|
|
59
60
|
rpcEntity.attributeSchema !== undefined ? decodeSchema(rpcEntity.attributeSchema) : undefined,
|
|
60
61
|
attributes:
|
|
@@ -23,7 +23,7 @@ function deadlineOf(expiresAt: bigint | Date, options?: DeadlineOptions): Expiry
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* Builds the `
|
|
26
|
+
* Builds the `expiration` of a create or an extension.
|
|
27
27
|
*
|
|
28
28
|
* Every helper returns the `{ minLifetime, expiresAt }` pair the ABI carries, so what you write is
|
|
29
29
|
* what goes on the wire. The `from*` helpers fill `minLifetime` and leave `expiresAt` at `0n`;
|
|
@@ -34,14 +34,14 @@ function deadlineOf(expiresAt: bigint | Date, options?: DeadlineOptions): Expiry
|
|
|
34
34
|
* object.
|
|
35
35
|
*
|
|
36
36
|
* @example The 90% case: a duration, and nothing else to think about.
|
|
37
|
-
* await client.createEntity(
|
|
37
|
+
* await client.createEntity(Posts, values, { expiration: ExpirationTime.fromDays(30) })
|
|
38
38
|
*
|
|
39
39
|
* @example An exact block, or a wall-clock date.
|
|
40
|
-
*
|
|
41
|
-
*
|
|
40
|
+
* expiration: ExpirationTime.atBlock(1_200_000n)
|
|
41
|
+
* expiration: ExpirationTime.atDate(new Date("2027-01-01"))
|
|
42
42
|
*
|
|
43
43
|
* @example A deadline that still guarantees a minimum life.
|
|
44
|
-
*
|
|
44
|
+
* expiration: ExpirationTime.atBlock(1_200_000n, { atLeast: ExpirationTime.fromDays(1) })
|
|
45
45
|
*/
|
|
46
46
|
export const ExpirationTime = {
|
|
47
47
|
/**
|
package/src/utils/index.ts
CHANGED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test"
|
|
2
|
+
import { getLogger } from "./logger"
|
|
3
|
+
|
|
4
|
+
describe("getLogger", () => {
|
|
5
|
+
const originalDebug = process.env.DEBUG
|
|
6
|
+
let log: ReturnType<typeof spyOn<Console, "log">>
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
log = spyOn(console, "log").mockImplementation(() => {})
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
log.mockRestore()
|
|
14
|
+
if (originalDebug === undefined) delete process.env.DEBUG
|
|
15
|
+
else process.env.DEBUG = originalDebug
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
/** Which of `scopes` log anything under `debug`. */
|
|
19
|
+
function enabledScopes(debug: string, scopes: string[]): string[] {
|
|
20
|
+
process.env.DEBUG = debug
|
|
21
|
+
return scopes.filter((scope) => {
|
|
22
|
+
log.mockClear()
|
|
23
|
+
getLogger(scope)("hello")
|
|
24
|
+
return log.mock.calls.length > 0
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
test("logs only the namespaces a pattern names", () => {
|
|
29
|
+
expect(enabledScopes("arkiv:a", ["a", "b"])).toEqual(["a"])
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test("a wildcard enables every namespace under its prefix", () => {
|
|
33
|
+
expect(enabledScopes("arkiv:*", ["a", "b"])).toEqual(["a", "b"])
|
|
34
|
+
expect(enabledScopes("arkiv:a:*", ["a:x", "a:y", "b:x"])).toEqual(["a:x", "a:y"])
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test("a -pattern excludes what it matches and leaves the rest enabled", () => {
|
|
38
|
+
expect(enabledScopes("arkiv:*,-arkiv:a", ["a", "b", "c"])).toEqual(["b", "c"])
|
|
39
|
+
expect(enabledScopes("arkiv:* -arkiv:a:*", ["a:x", "a:y", "b:x"])).toEqual(["b:x"])
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test("an exclusion alone enables nothing", () => {
|
|
43
|
+
expect(enabledScopes("-arkiv:a", ["a", "b"])).toEqual([])
|
|
44
|
+
})
|
|
45
|
+
})
|
package/src/utils/logger.ts
CHANGED
|
@@ -23,7 +23,8 @@ function getDebugEnv(): string {
|
|
|
23
23
|
return ""
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
//
|
|
26
|
+
// Check if a namespace matches a single positive pattern. Exclusions ("-pattern") are handled by
|
|
27
|
+
// isEnabled, which strips the "-" and calls this with the rest.
|
|
27
28
|
function matchesPattern(namespace: string, pattern: string): boolean {
|
|
28
29
|
// Exact match
|
|
29
30
|
if (pattern === namespace) return true
|
|
@@ -34,12 +35,6 @@ function matchesPattern(namespace: string, pattern: string): boolean {
|
|
|
34
35
|
return namespace.startsWith(prefix)
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
// Negative match: "-arkiv:query" excludes "arkiv:query"
|
|
38
|
-
if (pattern.startsWith("-")) {
|
|
39
|
-
const excludePattern = pattern.slice(1)
|
|
40
|
-
return !matchesPattern(namespace, excludePattern)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
38
|
return false
|
|
44
39
|
}
|
|
45
40
|
|
|
@@ -58,8 +53,8 @@ function isEnabled(namespace: string): boolean {
|
|
|
58
53
|
let enabled = false
|
|
59
54
|
for (const pattern of patterns) {
|
|
60
55
|
if (pattern.startsWith("-")) {
|
|
61
|
-
// Exclude pattern -
|
|
62
|
-
if (matchesPattern(namespace, pattern)) {
|
|
56
|
+
// Exclude pattern: "-arkiv:query" disables "arkiv:query" whatever else enables it
|
|
57
|
+
if (matchesPattern(namespace, pattern.slice(1))) {
|
|
63
58
|
return false
|
|
64
59
|
}
|
|
65
60
|
} else if (matchesPattern(namespace, pattern)) {
|
|
@@ -70,10 +65,6 @@ function isEnabled(namespace: string): boolean {
|
|
|
70
65
|
return enabled
|
|
71
66
|
}
|
|
72
67
|
|
|
73
|
-
// Store enabled namespaces (for programmatic enable/disable)
|
|
74
|
-
const enabledNamespaces: Set<string> = new Set()
|
|
75
|
-
const disabledNamespaces: Set<string> = new Set()
|
|
76
|
-
|
|
77
68
|
// Color palette for namespace coloring (distinct, readable colors)
|
|
78
69
|
const COLOR_PALETTE = [
|
|
79
70
|
"#0000FF", // blue
|
|
@@ -161,11 +152,7 @@ function createDebugLogger(namespace: string): DebugLogger {
|
|
|
161
152
|
const colors = getColorForNamespace(namespace)
|
|
162
153
|
|
|
163
154
|
return (...args: unknown[]) => {
|
|
164
|
-
|
|
165
|
-
const envEnabled = isEnabled(namespace)
|
|
166
|
-
const progEnabled = enabledNamespaces.has(namespace) && !disabledNamespaces.has(namespace)
|
|
167
|
-
|
|
168
|
-
if (envEnabled || progEnabled) {
|
|
155
|
+
if (isEnabled(namespace)) {
|
|
169
156
|
if (isNode) {
|
|
170
157
|
// Node.js: use ANSI color codes
|
|
171
158
|
const coloredNamespace = `${ANSI_BOLD}${colors.ansi}${namespace}${ANSI_RESET}`
|
|
@@ -187,24 +174,3 @@ export const getLogger = (scope: string): DebugLogger => {
|
|
|
187
174
|
const namespace = `${ROOT_NAMESPACE}:${scope}`
|
|
188
175
|
return createDebugLogger(namespace)
|
|
189
176
|
}
|
|
190
|
-
|
|
191
|
-
export const enableDebug = (namespaces: string): void => {
|
|
192
|
-
// Parse and add namespaces to enabled set
|
|
193
|
-
const patterns = namespaces.split(/[\s,]+/).filter((p) => p.length > 0)
|
|
194
|
-
for (const pattern of patterns) {
|
|
195
|
-
if (pattern.startsWith("-")) {
|
|
196
|
-
// Remove from enabled, add to disabled
|
|
197
|
-
const namespace = pattern.slice(1)
|
|
198
|
-
enabledNamespaces.delete(namespace)
|
|
199
|
-
disabledNamespaces.add(namespace)
|
|
200
|
-
} else {
|
|
201
|
-
enabledNamespaces.add(pattern)
|
|
202
|
-
disabledNamespaces.delete(pattern)
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
export const disableDebug = (): void => {
|
|
208
|
-
enabledNamespaces.clear()
|
|
209
|
-
disabledNamespaces.clear()
|
|
210
|
-
}
|
package/src/utils/revert.test.ts
CHANGED
|
@@ -65,6 +65,31 @@ describe("describeEntityRevert", () => {
|
|
|
65
65
|
})
|
|
66
66
|
})
|
|
67
67
|
|
|
68
|
+
describe("the indexed flag", () => {
|
|
69
|
+
it("says an indexed bytes attribute is the problem, not an unknown type", () => {
|
|
70
|
+
// bytes is typeId 7; bit 7 is the indexed flag.
|
|
71
|
+
expect(describeEntityRevert(reverted("InvalidValueType", [ident("body"), 0x87]))).toBe(
|
|
72
|
+
'"body" is a bytes attribute flagged as indexed, and bytes are stored but never indexed',
|
|
73
|
+
)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it("names the type and the flag when the node refuses an indexed attribute", () => {
|
|
77
|
+
// str is typeId 8; with bit 7 set, a node that predates the flag sees 0x88.
|
|
78
|
+
const message = describeEntityRevert(reverted("InvalidValueType", [ident("category"), 0x88]))
|
|
79
|
+
expect(message).toContain('"category" has type str and is flagged as indexed (type id 136)')
|
|
80
|
+
expect(message).toContain("may not support the indexed flag")
|
|
81
|
+
})
|
|
82
|
+
it("names the type when the node refuses an unindexed one", () => {
|
|
83
|
+
const message = describeEntityRevert(reverted("InvalidValueType", [ident("title"), 0x08]))
|
|
84
|
+
expect(message).toContain('"title" has type str (type id 8), which the node does not accept')
|
|
85
|
+
})
|
|
86
|
+
it("still reports a type id it cannot read as unknown", () => {
|
|
87
|
+
expect(describeEntityRevert(reverted("InvalidValueType", [ident("x"), 0xff]))).toContain(
|
|
88
|
+
"type id 255, which is not a known type",
|
|
89
|
+
)
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
68
93
|
describe("entity state", () => {
|
|
69
94
|
it("abbreviates the key so it does not bury the sentence", () => {
|
|
70
95
|
const message = describeEntityRevert(reverted("EntityNotFound", [KEY]))
|
package/src/utils/revert.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { BaseError, ContractFunctionRevertedError, type Hex, hexToString } from "viem"
|
|
2
|
+
// Internal seam: the typeId layout is the protocol's, not part of the package's public surface.
|
|
3
|
+
import { decodeTypeId } from "../schema/codec"
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Turns a decoded engine revert into a sentence that says what to change.
|
|
@@ -44,8 +46,8 @@ function explain(name: string, args: readonly unknown[]): string | undefined {
|
|
|
44
46
|
// ── the attribute list ───────────────────────────────────────────────────
|
|
45
47
|
case "SystemAttributeNotWritable":
|
|
46
48
|
return (
|
|
47
|
-
`"${identName(args[0])}" is owned by the engine and cannot be written.
|
|
48
|
-
"$
|
|
49
|
+
`"${identName(args[0])}" is owned by the engine and cannot be written. Names starting ` +
|
|
50
|
+
'with "$" are reserved for system attributes'
|
|
49
51
|
)
|
|
50
52
|
case "TombstoneInCreate":
|
|
51
53
|
return (
|
|
@@ -55,7 +57,7 @@ function explain(name: string, args: readonly unknown[]): string | undefined {
|
|
|
55
57
|
case "TombstoneValueNotEmpty":
|
|
56
58
|
return `the tombstone for "${identName(args[0])}" carries a value; unsetting takes no value`
|
|
57
59
|
case "InvalidValueType":
|
|
58
|
-
return
|
|
60
|
+
return describeInvalidType(identName(args[0]), Number(args[1]))
|
|
59
61
|
case "AttributesNotSorted":
|
|
60
62
|
return "attributes must be strictly ascending by name, which also makes each name unique"
|
|
61
63
|
case "TooManyAttributes":
|
|
@@ -117,6 +119,29 @@ function explain(name: string, args: readonly unknown[]): string | undefined {
|
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Why the engine refused a `typeId` — an indexed `bytes`, a known type it would not take (most
|
|
124
|
+
* likely the indexed flag, on a node that predates it), or a type it does not know.
|
|
125
|
+
*/
|
|
126
|
+
function describeInvalidType(name: string, typeId: number): string {
|
|
127
|
+
try {
|
|
128
|
+
const { tag, indexed } = decodeTypeId(typeId)
|
|
129
|
+
if (tag === "bytes" && indexed) {
|
|
130
|
+
return `"${name}" is a bytes attribute flagged as indexed, and bytes are stored but never indexed`
|
|
131
|
+
}
|
|
132
|
+
if (indexed) {
|
|
133
|
+
return (
|
|
134
|
+
`"${name}" has type ${tag} and is flagged as indexed (type id ${typeId}), which the node ` +
|
|
135
|
+
"does not accept. The node may not support the indexed flag yet"
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
return `"${name}" has type ${tag} (type id ${typeId}), which the node does not accept`
|
|
139
|
+
} catch {
|
|
140
|
+
// Falls through to the generic reading: the low bits name no type the SDK knows either.
|
|
141
|
+
}
|
|
142
|
+
return `"${name}" names type id ${typeId}, which is not a known type`
|
|
143
|
+
}
|
|
144
|
+
|
|
120
145
|
/** A `bytes32` Ident32 cell as the name it holds — left-aligned, null-padded. */
|
|
121
146
|
function identName(raw: unknown): string {
|
|
122
147
|
if (typeof raw !== "string") return String(raw)
|
package/dist/attr/index.cjs
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
const require_attr = require('../attr-BXTkpnoc.cjs');
|
|
2
|
-
|
|
3
|
-
exports.ConflictingMutationError = require_attr.ConflictingMutationError;
|
|
4
|
-
exports.DECIMAL_SCALE = require_attr.DECIMAL_SCALE;
|
|
5
|
-
exports.DECIMAL_UNIT = require_attr.DECIMAL_UNIT;
|
|
6
|
-
exports.I32_MAX = require_attr.I32_MAX;
|
|
7
|
-
exports.I32_MIN = require_attr.I32_MIN;
|
|
8
|
-
exports.InvalidAttributeNameError = require_attr.InvalidAttributeNameError;
|
|
9
|
-
exports.InvalidValueError = require_attr.InvalidValueError;
|
|
10
|
-
exports.MAX_ATTRIBUTES = require_attr.MAX_ATTRIBUTES;
|
|
11
|
-
exports.MAX_NAME_BYTES = require_attr.MAX_NAME_BYTES;
|
|
12
|
-
exports.MAX_PAYLOAD_BYTES = require_attr.MAX_PAYLOAD_BYTES;
|
|
13
|
-
exports.MAX_STRING_BYTES = require_attr.MAX_STRING_BYTES;
|
|
14
|
-
exports.MissingValueError = require_attr.MissingValueError;
|
|
15
|
-
exports.TooManyAttributesError = require_attr.TooManyAttributesError;
|
|
16
|
-
exports.U256_MAX = require_attr.U256_MAX;
|
|
17
|
-
exports.U64_MAX = require_attr.U64_MAX;
|
|
18
|
-
exports.UnknownAttributeTypeError = require_attr.UnknownAttributeTypeError;
|
|
19
|
-
exports.UntypedValueError = require_attr.UntypedValueError;
|
|
20
|
-
exports.addr = require_attr.addr;
|
|
21
|
-
exports.bool = require_attr.bool;
|
|
22
|
-
exports.bytes32 = require_attr.bytes32;
|
|
23
|
-
exports.dec = require_attr.dec;
|
|
24
|
-
exports.decFromUnits = require_attr.decFromUnits;
|
|
25
|
-
exports.decUnits = require_attr.decUnits;
|
|
26
|
-
exports.i32 = require_attr.i32;
|
|
27
|
-
exports.isArkivValue = require_attr.isArkivValue;
|
|
28
|
-
exports.isValidAttributeName = require_attr.isValidAttributeName;
|
|
29
|
-
exports.key = require_attr.key;
|
|
30
|
-
exports.str = require_attr.str;
|
|
31
|
-
exports.toValue = require_attr.toValue;
|
|
32
|
-
exports.u256 = require_attr.u256;
|
|
33
|
-
exports.u64 = require_attr.u64;
|
|
34
|
-
exports.validateAttributeName = require_attr.validateAttributeName;
|
package/dist/attr/index.d.cts
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { A as i32, B as Bytes32Value, C as ValueInput, D as dec, E as bytes32, F as u64, G as StrValue, H as DecValue, I as AddrValue, J as U64Value, K as TypeTag, L as AnyArkivValue, M as str, N as toValue, O as decFromUnits, P as u256, R as ArkivValue, S as U64_MAX, T as bool, U as I32Value, V as BytesValue, W as KeyValue, X as isArkivValue, Y as UserTypeTag, _ as MAX_PAYLOAD_BYTES, a as InvalidAttributeNameError, b as MAX_STRING_BYTES, c as TooManyAttributesError, d as DECIMAL_SCALE, f as DECIMAL_UNIT, g as MAX_ATTRIBUTES, h as Attributes, i as ConflictingMutationError, j as key, k as decUnits, l as UnknownAttributeTypeError, m as AttributeSchema, n as isValidAttributeName, o as InvalidValueError, p as AttributeInputs, q as U256Value, r as validateAttributeName, s as MissingValueError, t as MAX_NAME_BYTES, u as UntypedValueError, v as I32_MAX, w as addr, x as U256_MAX, y as I32_MIN, z as BoolValue } from "../index-CIcHPx2j.cjs";
|
|
2
|
-
export { AddrValue, AnyArkivValue, ArkivValue, AttributeInputs, AttributeSchema, Attributes, BoolValue, Bytes32Value, BytesValue, ConflictingMutationError, DECIMAL_SCALE, DECIMAL_UNIT, DecValue, I32Value, I32_MAX, I32_MIN, InvalidAttributeNameError, InvalidValueError, KeyValue, MAX_ATTRIBUTES, MAX_NAME_BYTES, MAX_PAYLOAD_BYTES, MAX_STRING_BYTES, MissingValueError, StrValue, TooManyAttributesError, TypeTag, U256Value, U256_MAX, U64Value, U64_MAX, UnknownAttributeTypeError, UntypedValueError, UserTypeTag, ValueInput, addr, bool, bytes32, dec, decFromUnits, decUnits, i32, isArkivValue, isValidAttributeName, key, str, toValue, u256, u64, validateAttributeName };
|
package/dist/attr/index.d.ts
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { A as i32, B as Bytes32Value, C as ValueInput, D as dec, E as bytes32, F as u64, G as StrValue, H as DecValue, I as AddrValue, J as U64Value, K as TypeTag, L as AnyArkivValue, M as str, N as toValue, O as decFromUnits, P as u256, R as ArkivValue, S as U64_MAX, T as bool, U as I32Value, V as BytesValue, W as KeyValue, X as isArkivValue, Y as UserTypeTag, _ as MAX_PAYLOAD_BYTES, a as InvalidAttributeNameError, b as MAX_STRING_BYTES, c as TooManyAttributesError, d as DECIMAL_SCALE, f as DECIMAL_UNIT, g as MAX_ATTRIBUTES, h as Attributes, i as ConflictingMutationError, j as key, k as decUnits, l as UnknownAttributeTypeError, m as AttributeSchema, n as isValidAttributeName, o as InvalidValueError, p as AttributeInputs, q as U256Value, r as validateAttributeName, s as MissingValueError, t as MAX_NAME_BYTES, u as UntypedValueError, v as I32_MAX, w as addr, x as U256_MAX, y as I32_MIN, z as BoolValue } from "../index-Cd2aaWme.js";
|
|
2
|
-
export { AddrValue, AnyArkivValue, ArkivValue, AttributeInputs, AttributeSchema, Attributes, BoolValue, Bytes32Value, BytesValue, ConflictingMutationError, DECIMAL_SCALE, DECIMAL_UNIT, DecValue, I32Value, I32_MAX, I32_MIN, InvalidAttributeNameError, InvalidValueError, KeyValue, MAX_ATTRIBUTES, MAX_NAME_BYTES, MAX_PAYLOAD_BYTES, MAX_STRING_BYTES, MissingValueError, StrValue, TooManyAttributesError, TypeTag, U256Value, U256_MAX, U64Value, U64_MAX, UnknownAttributeTypeError, UntypedValueError, UserTypeTag, ValueInput, addr, bool, bytes32, dec, decFromUnits, decUnits, i32, isArkivValue, isValidAttributeName, key, str, toValue, u256, u64, validateAttributeName };
|
package/dist/attr/index.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { A as DECIMAL_UNIT, C as str, E as u64, F as TooManyAttributesError, I as UnknownAttributeTypeError, L as UntypedValueError, M as InvalidAttributeNameError, N as InvalidValueError, O as isArkivValue, P as MissingValueError, S as key, T as u256, _ as bytes32, a as MAX_NAME_BYTES, b as decUnits, d as I32_MIN, f as MAX_STRING_BYTES, g as bool, h as addr, j as ConflictingMutationError, k as DECIMAL_SCALE, m as U64_MAX, n as MAX_PAYLOAD_BYTES, o as isValidAttributeName, p as U256_MAX, s as validateAttributeName, t as MAX_ATTRIBUTES, u as I32_MAX, v as dec, w as toValue, x as i32, y as decFromUnits } from "../attr-tmyREHtw.js";
|
|
2
|
-
|
|
3
|
-
export { ConflictingMutationError, DECIMAL_SCALE, DECIMAL_UNIT, I32_MAX, I32_MIN, InvalidAttributeNameError, InvalidValueError, MAX_ATTRIBUTES, MAX_NAME_BYTES, MAX_PAYLOAD_BYTES, MAX_STRING_BYTES, MissingValueError, TooManyAttributesError, U256_MAX, U64_MAX, UnknownAttributeTypeError, UntypedValueError, addr, bool, bytes32, dec, decFromUnits, decUnits, i32, isArkivValue, isValidAttributeName, key, str, toValue, u256, u64, validateAttributeName };
|