@arkiv-network/sdk 0.7.0-dev.1 → 0.8.0-dev.1
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 +29 -16
- package/dist/attr/index.cjs +34 -0
- package/dist/attr/index.d.cts +2 -0
- package/dist/attr/index.d.ts +2 -0
- package/dist/attr/index.js +3 -0
- package/dist/attr-BDZ-APg5.js +809 -0
- package/dist/attr-BDZ-APg5.js.map +1 -0
- package/dist/attr-BvxHN99W.cjs +1029 -0
- package/dist/chains/index.cjs +2 -3
- package/dist/chains/index.d.cts +22 -60
- package/dist/chains/index.d.cts.map +1 -1
- package/dist/chains/index.d.ts +22 -60
- package/dist/chains/index.d.ts.map +1 -1
- package/dist/chains/index.js +2 -2
- package/dist/chains-BJrZs6sG.js +57 -0
- package/dist/chains-BJrZs6sG.js.map +1 -0
- package/dist/chains-BYRTTipa.cjs +73 -0
- package/dist/changeOwnership-B7bEgla4.d.cts +509 -0
- package/dist/changeOwnership-B7bEgla4.d.cts.map +1 -0
- package/dist/changeOwnership-DwgtdSFc.d.ts +509 -0
- package/dist/changeOwnership-DwgtdSFc.d.ts.map +1 -0
- package/dist/entity/index.cjs +19 -0
- package/dist/entity/index.d.cts +4 -0
- package/dist/entity/index.d.ts +4 -0
- package/dist/entity/index.js +6 -0
- package/dist/entity-B0t6sN7F.cjs +71 -0
- package/dist/entity-BIp_df9u.js +67 -0
- package/dist/entity-BIp_df9u.js.map +1 -0
- package/dist/entity-CFhbAv0R.js +70 -0
- package/dist/entity-CFhbAv0R.js.map +1 -0
- package/dist/entity-wfBnZd91.cjs +98 -0
- package/dist/errors-D-eJkGVc.cjs +56 -0
- package/dist/errors-DGB8AgT2.js +33 -0
- package/dist/errors-DGB8AgT2.js.map +1 -0
- package/dist/expiry-BUYIXTGb.cjs +135 -0
- package/dist/expiry-BxOlvVWC.d.ts +79 -0
- package/dist/expiry-BxOlvVWC.d.ts.map +1 -0
- package/dist/expiry-DGRzrSan.js +95 -0
- package/dist/expiry-DGRzrSan.js.map +1 -0
- package/dist/expiry-DRV29F1r.d.cts +79 -0
- package/dist/expiry-DRV29F1r.d.cts.map +1 -0
- package/dist/flags-0Vl5rrHq.d.cts +41 -0
- package/dist/flags-0Vl5rrHq.d.cts.map +1 -0
- package/dist/flags-Ct8k0gpB.cjs +43 -0
- package/dist/flags-ZtlvOIIk.js +33 -0
- package/dist/flags-ZtlvOIIk.js.map +1 -0
- package/dist/flags-wmcMoAnN.d.ts +41 -0
- package/dist/flags-wmcMoAnN.d.ts.map +1 -0
- package/dist/index-Cgw1u5aY.d.cts +278 -0
- package/dist/index-Cgw1u5aY.d.cts.map +1 -0
- package/dist/index-ClgIuxJ8.d.ts +159 -0
- package/dist/index-ClgIuxJ8.d.ts.map +1 -0
- package/dist/index-D0CmtiWT.d.cts +159 -0
- package/dist/index-D0CmtiWT.d.cts.map +1 -0
- package/dist/index-D8LZt-3J.d.cts +417 -0
- package/dist/index-D8LZt-3J.d.cts.map +1 -0
- package/dist/index-DVYFaXNV.d.ts +417 -0
- package/dist/index-DVYFaXNV.d.ts.map +1 -0
- package/dist/index-VCqgn29D.d.ts +278 -0
- package/dist/index-VCqgn29D.d.ts.map +1 -0
- package/dist/index.cjs +676 -375
- package/dist/index.d.cts +247 -208
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +247 -208
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +626 -368
- package/dist/index.js.map +1 -1
- package/dist/payload-Bnw1hrvb.cjs +83 -0
- package/dist/payload-CIxSn_DW.js +67 -0
- package/dist/payload-CIxSn_DW.js.map +1 -0
- package/dist/payload-Dgx3PQeK.d.ts +94 -0
- package/dist/payload-Dgx3PQeK.d.ts.map +1 -0
- package/dist/payload-P0nWyjLg.d.cts +94 -0
- package/dist/payload-P0nWyjLg.d.cts.map +1 -0
- package/dist/query/index.cjs +24 -150
- package/dist/query/index.d.cts +5 -3
- package/dist/query/index.d.ts +5 -3
- package/dist/query/index.js +6 -138
- package/dist/queryBuilder-BXDvX1K_.cjs +1123 -0
- package/dist/queryBuilder-CbLL4pG5.js +963 -0
- package/dist/queryBuilder-CbLL4pG5.js.map +1 -0
- package/dist/selection-BvK6yX0g.d.cts +433 -0
- package/dist/selection-BvK6yX0g.d.cts.map +1 -0
- package/dist/selection-fpmI3ADQ.d.ts +433 -0
- package/dist/selection-fpmI3ADQ.d.ts.map +1 -0
- package/dist/types/index.cjs +3 -3
- package/dist/types/index.d.cts +7 -2
- package/dist/types/index.d.ts +7 -2
- package/dist/types/index.js +3 -3
- package/dist/utils/index.cjs +4 -17
- package/dist/utils/index.d.cts +3 -17
- package/dist/utils/index.d.ts +3 -17
- package/dist/utils/index.js +4 -18
- package/package.json +26 -5
- package/src/actions/public/getEntity.ts +27 -43
- package/src/actions/public/getEntityNonce.ts +30 -0
- package/src/actions/public/predictEntityKeys.test.ts +143 -0
- package/src/actions/public/predictEntityKeys.ts +138 -0
- package/src/actions/public/query.ts +33 -69
- package/src/actions/public/watchEntityEvents.test.ts +414 -0
- package/src/actions/public/watchEntityEvents.ts +225 -0
- package/src/actions/wallet/changeOwnership.ts +2 -2
- package/src/actions/wallet/createEntity.ts +99 -24
- package/src/actions/wallet/extendEntity.ts +37 -13
- package/src/actions/wallet/mutateEntities.test.ts +76 -0
- package/src/actions/wallet/mutateEntities.ts +19 -21
- package/src/actions/wallet/patchEntity.ts +90 -0
- package/src/attr/attributes.test.ts +120 -0
- package/src/attr/attributes.ts +190 -0
- package/src/attr/codec.test.ts +162 -0
- package/src/attr/codec.ts +220 -0
- package/src/attr/decimal.ts +86 -0
- package/src/attr/errors.ts +145 -0
- package/src/attr/index.ts +50 -0
- package/src/attr/names.ts +106 -0
- package/src/attr/types.ts +150 -0
- package/src/attr/values.test.ts +271 -0
- package/src/attr/values.ts +502 -0
- package/src/chains/cheesecake.ts +22 -0
- package/src/chains/index.ts +1 -2
- package/src/clients/createPublicClient.test.ts +3 -5
- package/src/clients/createPublicClient.ts +5 -4
- package/src/clients/createWalletClient.test.ts +2 -2
- package/src/clients/createWalletClient.ts +13 -7
- package/src/clients/decorators/arkivPublic.ts +160 -139
- package/src/clients/decorators/arkivWallet.ts +86 -94
- package/src/entity/create.test.ts +184 -0
- package/src/entity/errors.ts +38 -0
- package/src/entity/events.ts +16 -0
- package/src/entity/expiry.test.ts +195 -0
- package/src/entity/expiry.ts +181 -0
- package/src/entity/flags.ts +65 -0
- package/src/entity/index.ts +14 -0
- package/src/entity/key.ts +68 -0
- package/src/entity/operations.ts +134 -0
- package/src/entity/params.ts +15 -0
- package/src/errors.ts +26 -49
- package/src/index.ts +6 -0
- package/src/query/engine.ts +59 -139
- package/src/query/errors.ts +151 -0
- package/src/query/expression.test.ts +286 -0
- package/src/query/expression.ts +493 -0
- package/src/query/index.ts +40 -4
- package/src/query/injection.test.ts +151 -0
- package/src/query/queryBuilder.test.ts +322 -637
- package/src/query/queryBuilder.ts +126 -359
- package/src/query/queryResult.ts +54 -51
- package/src/query/selection.test.ts +48 -98
- package/src/query/selection.ts +77 -65
- package/src/types/entity.test.ts +44 -155
- package/src/types/entity.ts +60 -52
- package/src/types/events.ts +59 -16
- package/src/types/index.ts +20 -17
- package/src/types/rpcSchema.ts +69 -37
- package/src/utils/arkivTransactions.test.ts +600 -155
- package/src/utils/arkivTransactions.ts +181 -190
- package/src/utils/chains.test.ts +21 -24
- package/src/utils/compression.ts +1 -1
- package/src/utils/entities.test.ts +62 -0
- package/src/utils/entities.ts +109 -37
- package/src/utils/expirationTime.ts +114 -10
- package/src/utils/logger.ts +2 -2
- package/src/utils/revert.test.ts +99 -0
- package/src/utils/revert.ts +145 -0
- package/dist/chains-BifaY04V.cjs +0 -108
- package/dist/chains-CrtkVbBh.js +0 -86
- package/dist/chains-CrtkVbBh.js.map +0 -1
- package/dist/consts-Bz0LZQZY.js +0 -7
- package/dist/consts-Bz0LZQZY.js.map +0 -1
- package/dist/consts-CxT1-RXU.cjs +0 -18
- package/dist/entity-BhSXaB23.cjs +0 -81
- package/dist/entity-CN41IOrq.d.cts +0 -401
- package/dist/entity-CN41IOrq.d.cts.map +0 -1
- package/dist/entity-DGfVyB-a.js +0 -71
- package/dist/entity-DGfVyB-a.js.map +0 -1
- package/dist/entity-NnEVlePN.d.ts +0 -401
- package/dist/entity-NnEVlePN.d.ts.map +0 -1
- package/dist/index-ClkpS6s_.d.ts +0 -481
- package/dist/index-ClkpS6s_.d.ts.map +0 -1
- package/dist/index-w4qop0Pe.d.cts +0 -481
- package/dist/index-w4qop0Pe.d.cts.map +0 -1
- package/dist/payload-BpNUPOnY.js +0 -13
- package/dist/payload-BpNUPOnY.js.map +0 -1
- package/dist/payload-C2KHOUoj.d.ts +0 -6
- package/dist/payload-C2KHOUoj.d.ts.map +0 -1
- package/dist/payload-CJN8fTvX.d.cts +0 -6
- package/dist/payload-CJN8fTvX.d.cts.map +0 -1
- package/dist/payload-D8YLKcJj.cjs +0 -23
- package/dist/query/index.js.map +0 -1
- package/dist/queryBuilder-BE_XhLLa.js +0 -735
- package/dist/queryBuilder-BE_XhLLa.js.map +0 -1
- package/dist/queryBuilder-J37buGCi.cjs +0 -865
- package/dist/utils/index.d.cts.map +0 -1
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js.map +0 -1
- package/src/actions/public/buildQuery.ts +0 -10
- package/src/actions/public/subscribeEntityEvents.ts +0 -93
- package/src/actions/wallet/updateEntity.ts +0 -59
- package/src/chains/braga.ts +0 -26
- package/src/chains/kaolin.ts +0 -29
- package/src/query/engine.test.ts +0 -571
- package/src/query/predicate.test.ts +0 -461
- package/src/query/predicate.ts +0 -144
- package/src/query/queryResult.test.ts +0 -270
- package/src/query/selectQueryBuilder.test.ts +0 -213
- package/src/types/attributes.ts +0 -28
- package/src/utils/validation.test.ts +0 -106
- package/src/utils/validation.ts +0 -80
- /package/dist/{types-Ci4BRClw.js → types-Bx1EKe0v.js} +0 -0
- /package/dist/{types-a8gm_IaQ.cjs → types-CKPddlfS.cjs} +0 -0
package/src/utils/entities.ts
CHANGED
|
@@ -1,47 +1,119 @@
|
|
|
1
|
-
import { type Hex,
|
|
2
|
-
import type {
|
|
3
|
-
|
|
1
|
+
import { checksumAddress, type Hex, hexToBytes } from "viem"
|
|
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"
|
|
5
|
+
import {
|
|
6
|
+
decodeCreationFlags,
|
|
7
|
+
encodeCreationFlags,
|
|
8
|
+
type ResolvedCreationFlags,
|
|
9
|
+
} from "../entity/flags"
|
|
10
|
+
import { Entity, type EntityFields } from "../types/entity"
|
|
4
11
|
import type { RpcEntity } from "../types/rpcSchema"
|
|
5
|
-
import { RpcAttributeValueType } from "../types/rpcSchema"
|
|
6
12
|
import { getLogger } from "./logger"
|
|
7
13
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
const logger = getLogger("utils:entities")
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Turns the attribute array a query returns into a name-keyed map of typed values.
|
|
18
|
+
*
|
|
19
|
+
* Attribute names are unique per entity, so the map loses nothing and gives callers
|
|
20
|
+
* `entity.attributes.level.value` instead of a linear search.
|
|
21
|
+
*/
|
|
22
|
+
function decodeAttributes(rpcAttributes: NonNullable<RpcEntity["attributes"]>): Attributes {
|
|
23
|
+
const attributes: Record<string, ReturnType<typeof decodeRpcValue>> = {}
|
|
24
|
+
for (const { name, type, value } of rpcAttributes) {
|
|
25
|
+
attributes[name] = decodeRpcValue(type, value)
|
|
17
26
|
}
|
|
27
|
+
return attributes
|
|
18
28
|
}
|
|
19
29
|
|
|
20
|
-
|
|
30
|
+
/** The same, for the values-free `attributeSchema` projection. */
|
|
31
|
+
function decodeSchema(entries: NonNullable<RpcEntity["attributeSchema"]>): AttributeSchema {
|
|
32
|
+
const schema: Record<string, ReturnType<typeof asTypeTag>> = {}
|
|
33
|
+
for (const { name, type } of entries) {
|
|
34
|
+
schema[name] = asTypeTag(type)
|
|
35
|
+
}
|
|
36
|
+
return schema
|
|
37
|
+
}
|
|
21
38
|
|
|
22
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Builds an {@link Entity} from a query result row.
|
|
41
|
+
*
|
|
42
|
+
* A field the query did not select is absent from the response and stays `undefined` here — the
|
|
43
|
+
* decoder never substitutes an empty value for one that was not asked for.
|
|
44
|
+
*/
|
|
45
|
+
export function entityFromRpcResult(rpcEntity: RpcEntity): Entity {
|
|
23
46
|
logger("entityFromRpcResult %o", rpcEntity)
|
|
24
47
|
|
|
25
|
-
|
|
26
|
-
rpcEntity.key,
|
|
27
|
-
rpcEntity.
|
|
28
|
-
rpcEntity.
|
|
29
|
-
rpcEntity.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
rpcEntity.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
: undefined,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
const fields: EntityFields = {
|
|
49
|
+
key: rpcEntity.key,
|
|
50
|
+
owner: toAddress(rpcEntity.owner),
|
|
51
|
+
creator: toAddress(rpcEntity.creator),
|
|
52
|
+
createdAt: toBlock(rpcEntity.createdAt),
|
|
53
|
+
updatedAt: toBlock(rpcEntity.updatedAt),
|
|
54
|
+
expiresAt: toBlock(rpcEntity.expiresAt),
|
|
55
|
+
creationFlags: decodeFlags(rpcEntity.creationFlags),
|
|
56
|
+
contentType: rpcEntity.contentType,
|
|
57
|
+
payload: rpcEntity.payload !== undefined ? hexToBytes(rpcEntity.payload) : undefined,
|
|
58
|
+
attributeSchema:
|
|
59
|
+
rpcEntity.attributeSchema !== undefined ? decodeSchema(rpcEntity.attributeSchema) : undefined,
|
|
60
|
+
attributes:
|
|
61
|
+
rpcEntity.attributes !== undefined ? decodeAttributes(rpcEntity.attributes) : undefined,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return new Entity(fields)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function toBlock(value: string | undefined): bigint | undefined {
|
|
68
|
+
return value === undefined ? undefined : BigInt(value)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function toAddress(value: Hex | undefined): Hex | undefined {
|
|
72
|
+
if (value === undefined) return undefined
|
|
73
|
+
if (!/^0x[0-9a-fA-F]{40}$/.test(value)) {
|
|
74
|
+
logger("unreadable address %o", value)
|
|
75
|
+
return value
|
|
76
|
+
}
|
|
77
|
+
return checksumAddress(value)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Resolves the `creationFlags` projection, preferring the byte.
|
|
82
|
+
*/
|
|
83
|
+
function decodeFlags(
|
|
84
|
+
value: NonNullable<RpcEntity["creationFlags"]> | undefined,
|
|
85
|
+
): ResolvedCreationFlags | undefined {
|
|
86
|
+
if (value === undefined) return undefined
|
|
87
|
+
|
|
88
|
+
const raw = toFlagsByte(typeof value === "number" ? value : value.raw)
|
|
89
|
+
if (raw !== undefined) return decodeCreationFlags(raw)
|
|
90
|
+
|
|
91
|
+
if (
|
|
92
|
+
typeof value === "object" &&
|
|
93
|
+
(value.readonly ?? value.permissionlessExtension) !== undefined
|
|
94
|
+
) {
|
|
95
|
+
return decodeCreationFlags(
|
|
96
|
+
encodeCreationFlags({
|
|
97
|
+
readonly: value.readonly ?? false,
|
|
98
|
+
permissionlessExtension: value.permissionlessExtension ?? false,
|
|
99
|
+
}),
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
logger("unreadable creationFlags %o", value)
|
|
104
|
+
return undefined
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* A flags byte in whichever spelling arrived: a JSON number, or the `0x` QUANTITY that every other
|
|
109
|
+
* numeric field on {@link RpcEntity} already uses. `undefined` for anything that is not a byte.
|
|
110
|
+
*/
|
|
111
|
+
function toFlagsByte(value: unknown): number | undefined {
|
|
112
|
+
const parsed =
|
|
113
|
+
typeof value === "number"
|
|
114
|
+
? value
|
|
115
|
+
: typeof value === "string" && /^(0x[0-9a-fA-F]+|\d+)$/.test(value)
|
|
116
|
+
? Number(value)
|
|
117
|
+
: Number.NaN
|
|
118
|
+
return Number.isInteger(parsed) && parsed >= 0 && parsed <= 0xff ? parsed : undefined
|
|
47
119
|
}
|
|
@@ -1,13 +1,117 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InvalidExpiryError } from "../entity/errors"
|
|
2
|
+
import { type Expiry, type Lifetime, makeExpiry, toBlocks } from "../entity/expiry"
|
|
3
|
+
import { MAX_EXPIRES_AT } from "../entity/params"
|
|
2
4
|
|
|
5
|
+
/**
|
|
6
|
+
* The optional floor a deadline can carry.
|
|
7
|
+
*
|
|
8
|
+
* `atLeast` takes a duration — one of the `from*` helpers — and never another deadline, so
|
|
9
|
+
* `atBlock(x, { atLeast: atBlock(y) })` does not compile. Two deadlines are not a thing the engine
|
|
10
|
+
* can resolve.
|
|
11
|
+
*/
|
|
12
|
+
export type DeadlineOptions = {
|
|
13
|
+
/** Live at least this long from now, even if the deadline is sooner. */
|
|
14
|
+
atLeast?: Lifetime | undefined
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function lifetimeOf(seconds: number): Lifetime {
|
|
18
|
+
return makeExpiry(toBlocks(seconds), 0n) as Lifetime
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function deadlineOf(expiresAt: bigint | Date, options?: DeadlineOptions): Expiry {
|
|
22
|
+
return makeExpiry(options?.atLeast?.minLifetime ?? 0n, expiresAt)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Builds the `expires` of a create or an extension.
|
|
27
|
+
*
|
|
28
|
+
* Every helper returns the `{ minLifetime, expiresAt }` pair the ABI carries, so what you write is
|
|
29
|
+
* what goes on the wire. The `from*` helpers fill `minLifetime` and leave `expiresAt` at `0n`;
|
|
30
|
+
* {@link ExpirationTime.atBlock} and {@link ExpirationTime.atDate} do the reverse. The engine takes
|
|
31
|
+
* whichever comes later, which is why a deadline can also carry a floor.
|
|
32
|
+
*
|
|
33
|
+
* Values are plain data — no methods, no prototype — so they log, clone and compare like any other
|
|
34
|
+
* object.
|
|
35
|
+
*
|
|
36
|
+
* @example The 90% case: a duration, and nothing else to think about.
|
|
37
|
+
* await client.createEntity({ payload, contentType, expires: ExpirationTime.fromDays(30) })
|
|
38
|
+
*
|
|
39
|
+
* @example An exact block, or a wall-clock date.
|
|
40
|
+
* expires: ExpirationTime.atBlock(1_200_000n)
|
|
41
|
+
* expires: ExpirationTime.atDate(new Date("2027-01-01"))
|
|
42
|
+
*
|
|
43
|
+
* @example A deadline that still guarantees a minimum life.
|
|
44
|
+
* expires: ExpirationTime.atBlock(1_200_000n, { atLeast: ExpirationTime.fromDays(1) })
|
|
45
|
+
*/
|
|
3
46
|
export const ExpirationTime = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
47
|
+
/**
|
|
48
|
+
* A raw number of seconds. Must be a whole number of blocks' worth — see the other helpers, which
|
|
49
|
+
* all produce one by construction.
|
|
50
|
+
*
|
|
51
|
+
* @throws {InvalidExpiryError} If the duration is not a positive multiple of the block time.
|
|
52
|
+
*/
|
|
53
|
+
fromSeconds: (seconds: number): Lifetime => lifetimeOf(seconds),
|
|
54
|
+
fromMinutes: (minutes: number): Lifetime => lifetimeOf(minutes * 60),
|
|
55
|
+
fromHours: (hours: number): Lifetime => lifetimeOf(hours * 60 * 60),
|
|
56
|
+
fromDays: (days: number): Lifetime => lifetimeOf(days * 24 * 60 * 60),
|
|
57
|
+
fromWeeks: (weeks: number): Lifetime => lifetimeOf(weeks * 7 * 24 * 60 * 60),
|
|
58
|
+
fromMonths: (months: number): Lifetime => lifetimeOf(months * 30 * 24 * 60 * 60),
|
|
59
|
+
fromYears: (years: number): Lifetime => lifetimeOf(years * 365 * 24 * 60 * 60),
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* A number of blocks, for callers who think in the chain's own unit. Always exact — there is no
|
|
63
|
+
* conversion to be approximate about.
|
|
64
|
+
*
|
|
65
|
+
* @throws {InvalidExpiryError} If the count is not a positive whole number.
|
|
66
|
+
*/
|
|
67
|
+
fromBlocks: (blocks: number): Lifetime => {
|
|
68
|
+
if (!Number.isInteger(blocks) || blocks <= 0) {
|
|
69
|
+
throw new InvalidExpiryError(
|
|
70
|
+
`a lifetime must be a positive whole number of blocks, got ${blocks}`,
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
return makeExpiry(BigInt(blocks), 0n) as Lifetime
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* An absolute block height.
|
|
78
|
+
*
|
|
79
|
+
* @param block - The block the entity expires at.
|
|
80
|
+
* @param options - Optionally, a floor: `{ atLeast: ExpirationTime.fromDays(1) }`.
|
|
81
|
+
* @throws {InvalidExpiryError} If the height is negative.
|
|
82
|
+
*/
|
|
83
|
+
atBlock: (block: bigint, options?: DeadlineOptions): Expiry => {
|
|
84
|
+
if (typeof block !== "bigint" || block < 0n) {
|
|
85
|
+
throw new InvalidExpiryError(`a deadline must be a non-negative block height, got ${block}`)
|
|
86
|
+
}
|
|
87
|
+
return deadlineOf(block, options)
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* A wall-clock instant, placed against the block the transaction is built on.
|
|
92
|
+
*
|
|
93
|
+
* A date cannot land on a block boundary in general, so it rounds **up** to the next block: the
|
|
94
|
+
* entity lives until at least the instant asked for. This is why a date is never rejected for
|
|
95
|
+
* "not being a whole number of blocks" the way a duration is — it becomes a block height, not a
|
|
96
|
+
* duration.
|
|
97
|
+
*
|
|
98
|
+
* @param date - When the entity should expire.
|
|
99
|
+
* @param options - Optionally, a floor: `{ atLeast: ExpirationTime.fromDays(1) }`.
|
|
100
|
+
* @throws {InvalidExpiryError} If the value is not a valid `Date`.
|
|
101
|
+
*/
|
|
102
|
+
atDate: (date: Date, options?: DeadlineOptions): Expiry => {
|
|
103
|
+
if (!(date instanceof Date) || Number.isNaN(date.getTime())) {
|
|
104
|
+
throw new InvalidExpiryError(`a deadline must be a valid Date, got ${String(date)}`)
|
|
105
|
+
}
|
|
106
|
+
return deadlineOf(date, options)
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* An entity that should never expire.
|
|
111
|
+
*
|
|
112
|
+
* This is `atBlock(MAX_EXPIRES_AT)` — the largest expiry the `uint64` field holds — and the
|
|
113
|
+
* engine treats it as an ordinary deadline rather than a special case. There is no permanence
|
|
114
|
+
* flag; a block height no chain will reach is what permanence is.
|
|
115
|
+
*/
|
|
116
|
+
permanent: (): Expiry => deadlineOf(MAX_EXPIRES_AT),
|
|
13
117
|
}
|
package/src/utils/logger.ts
CHANGED
|
@@ -144,8 +144,8 @@ function getColorForNamespace(namespace: string): { css: string; ansi: string }
|
|
|
144
144
|
|
|
145
145
|
// Use absolute value and modulo to get index
|
|
146
146
|
const colorIndex = Math.abs(hash) % COLOR_PALETTE.length
|
|
147
|
-
const cssColor = COLOR_PALETTE[colorIndex]
|
|
148
|
-
const ansiColor = ANSI_COLORS[colorIndex % ANSI_COLORS.length]
|
|
147
|
+
const cssColor = COLOR_PALETTE[colorIndex] ?? "inherit"
|
|
148
|
+
const ansiColor = ANSI_COLORS[colorIndex % ANSI_COLORS.length] ?? ""
|
|
149
149
|
|
|
150
150
|
const color = { css: cssColor, ansi: ansiColor }
|
|
151
151
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test"
|
|
2
|
+
import { BaseError, ContractFunctionRevertedError, type Hex, toHex } from "viem"
|
|
3
|
+
import { describeEntityRevert } from "./revert"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Wraps a decoded revert the way viem delivers one: the `ContractFunctionRevertedError` is nested
|
|
7
|
+
* in a cause chain, which is why `describeEntityRevert` walks rather than type-checks the top.
|
|
8
|
+
*/
|
|
9
|
+
function reverted(errorName: string, args: readonly unknown[]): BaseError {
|
|
10
|
+
const inner = new ContractFunctionRevertedError({
|
|
11
|
+
abi: [],
|
|
12
|
+
functionName: "execute",
|
|
13
|
+
})
|
|
14
|
+
// The constructor cannot build `data` without a real ABI decode, so it is set directly — the
|
|
15
|
+
// shape is what matters here, not how viem arrived at it.
|
|
16
|
+
Object.assign(inner, { data: { errorName, args } })
|
|
17
|
+
return new BaseError('The contract function "execute" reverted.', { cause: inner })
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** An Ident32 name cell: the name, left-aligned and null-padded to 32 bytes. */
|
|
21
|
+
const ident = (name: string): Hex => toHex(name, { size: 32 })
|
|
22
|
+
|
|
23
|
+
const KEY = `0x${"ab".repeat(32)}` as Hex
|
|
24
|
+
|
|
25
|
+
describe("describeEntityRevert", () => {
|
|
26
|
+
it("ignores anything that is not a decoded engine revert", () => {
|
|
27
|
+
expect(describeEntityRevert(new Error("boom"))).toBeUndefined()
|
|
28
|
+
expect(describeEntityRevert("boom")).toBeUndefined()
|
|
29
|
+
expect(describeEntityRevert(undefined)).toBeUndefined()
|
|
30
|
+
expect(describeEntityRevert(new BaseError("no cause"))).toBeUndefined()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
describe("attribute names", () => {
|
|
34
|
+
it("names the offending character rather than printing the byte alone", () => {
|
|
35
|
+
const message = describeEntityRevert(reverted("Ident32InvalidByte", [5n, "0x21"]))
|
|
36
|
+
expect(message).toContain('"!"')
|
|
37
|
+
expect(message).toContain("0x21")
|
|
38
|
+
expect(message).toContain("byte 5")
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it("quotes the name charset the SDK itself validates against", () => {
|
|
42
|
+
const message = describeEntityRevert(reverted("Ident32InvalidByte", [0n, "0x2f"]))
|
|
43
|
+
expect(message).toContain('"A"-"Z"')
|
|
44
|
+
expect(message).toContain('"a"-"z"')
|
|
45
|
+
expect(message).toContain("with a letter first")
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it("renders an unprintable byte as a byte", () => {
|
|
49
|
+
const message = describeEntityRevert(reverted("Ident32InvalidByte", [1n, "0x07"]))
|
|
50
|
+
expect(message).toContain("byte 0x07")
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
describe("names carried in a bytes32 cell", () => {
|
|
55
|
+
it("reads the name back out of its null padding", () => {
|
|
56
|
+
expect(
|
|
57
|
+
describeEntityRevert(reverted("SystemAttributeNotWritable", [ident("$owner")])),
|
|
58
|
+
).toContain('"$owner"')
|
|
59
|
+
expect(describeEntityRevert(reverted("TombstoneInCreate", [ident("gone")]))).toContain(
|
|
60
|
+
'"gone"',
|
|
61
|
+
)
|
|
62
|
+
expect(describeEntityRevert(reverted("InvalidValueType", [ident("level"), 99]))).toContain(
|
|
63
|
+
'"level"',
|
|
64
|
+
)
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
describe("entity state", () => {
|
|
69
|
+
it("abbreviates the key so it does not bury the sentence", () => {
|
|
70
|
+
const message = describeEntityRevert(reverted("EntityNotFound", [KEY]))
|
|
71
|
+
expect(message).toContain("…")
|
|
72
|
+
expect(message).not.toContain(KEY)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it("explains a readonly entity in terms of what is still allowed", () => {
|
|
76
|
+
const message = describeEntityRevert(reverted("ReadOnlyEntity", [KEY]))
|
|
77
|
+
expect(message).toContain("readonly")
|
|
78
|
+
expect(message).toContain("extended")
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it("renders reserved creation flags as the bits they are", () => {
|
|
82
|
+
const message = describeEntityRevert(reverted("ReservedCreationFlags", [0b100]))
|
|
83
|
+
expect(message).toContain("0b00000100")
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
describe("expiry", () => {
|
|
88
|
+
it("says which way the extension went wrong", () => {
|
|
89
|
+
const message = describeEntityRevert(reverted("ExpiryNotExtended", [KEY, 100n, 500n]))
|
|
90
|
+
expect(message).toContain("already expires at block 500")
|
|
91
|
+
expect(message).toContain("shorten")
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it("falls back to naming the error when it has no tailored explanation", () => {
|
|
96
|
+
const message = describeEntityRevert(reverted("SomeFutureError", []))
|
|
97
|
+
expect(message).toBe("the engine rejected the batch with SomeFutureError")
|
|
98
|
+
})
|
|
99
|
+
})
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { BaseError, ContractFunctionRevertedError, type Hex, hexToString } from "viem"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Turns a decoded engine revert into a sentence that says what to change.
|
|
5
|
+
*
|
|
6
|
+
* viem decodes the error and then renders it positionally — `Ident32InvalidByte(uint256 position,
|
|
7
|
+
* bytes1 value)` arrives as `(5, 0x41)`, which is the right data and no help at all. The engine's
|
|
8
|
+
* errors carry enough to name the actual problem, so this spends the args rather than printing
|
|
9
|
+
* them.
|
|
10
|
+
*
|
|
11
|
+
* @param error - Anything thrown by a write action.
|
|
12
|
+
* @returns The explanation, or `undefined` if this was not a decodable engine revert — in which
|
|
13
|
+
* case the caller should fall back to whatever the transport said.
|
|
14
|
+
*/
|
|
15
|
+
export function describeEntityRevert(error: unknown): string | undefined {
|
|
16
|
+
if (!(error instanceof BaseError)) return undefined
|
|
17
|
+
const reverted = error.walk((e) => e instanceof ContractFunctionRevertedError)
|
|
18
|
+
if (!(reverted instanceof ContractFunctionRevertedError)) return undefined
|
|
19
|
+
|
|
20
|
+
const name = reverted.data?.errorName
|
|
21
|
+
if (name === undefined) return undefined
|
|
22
|
+
const args = (reverted.data?.args ?? []) as readonly unknown[]
|
|
23
|
+
|
|
24
|
+
return explain(name, args) ?? `the engine rejected the batch with ${name}`
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** The attribute-name charset, quoted the way an error message should read. */
|
|
28
|
+
const CHARSET = '"A"-"Z", "a"-"z", "0"-"9", ".", "-" and "_", with a letter first'
|
|
29
|
+
|
|
30
|
+
function explain(name: string, args: readonly unknown[]): string | undefined {
|
|
31
|
+
switch (name) {
|
|
32
|
+
// ── attribute names ──────────────────────────────────────────────────────
|
|
33
|
+
case "Ident32InvalidByte": {
|
|
34
|
+
const position = Number(args[0] ?? 0)
|
|
35
|
+
const char = printable(String(args[1] ?? "0x00"))
|
|
36
|
+
return (
|
|
37
|
+
`an attribute name holds ${char} at byte ${position}, which is outside the ` +
|
|
38
|
+
`name charset (${CHARSET})`
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
case "Ident32Empty":
|
|
42
|
+
return "an attribute name is empty"
|
|
43
|
+
|
|
44
|
+
// ── the attribute list ───────────────────────────────────────────────────
|
|
45
|
+
case "SystemAttributeNotWritable":
|
|
46
|
+
return (
|
|
47
|
+
`"${identName(args[0])}" is owned by the engine and cannot be written. Only $payload and ` +
|
|
48
|
+
"$contentType are yours to set"
|
|
49
|
+
)
|
|
50
|
+
case "TombstoneInCreate":
|
|
51
|
+
return (
|
|
52
|
+
`a create cannot unset "${identName(args[0])}" — nothing exists yet, so leave the name ` +
|
|
53
|
+
"out instead"
|
|
54
|
+
)
|
|
55
|
+
case "TombstoneValueNotEmpty":
|
|
56
|
+
return `the tombstone for "${identName(args[0])}" carries a value; unsetting takes no value`
|
|
57
|
+
case "InvalidValueType":
|
|
58
|
+
return `"${identName(args[0])}" names type id ${String(args[1])}, which is not a known type`
|
|
59
|
+
case "AttributesNotSorted":
|
|
60
|
+
return "attributes must be strictly ascending by name, which also makes each name unique"
|
|
61
|
+
case "TooManyAttributes":
|
|
62
|
+
return `${String(args[0])} attributes exceeds the limit of ${String(args[1])}`
|
|
63
|
+
case "EmptyMutations":
|
|
64
|
+
return `the patch of ${short(args[0])} has no mutations, so it would do nothing`
|
|
65
|
+
|
|
66
|
+
// ── entity state and authorisation ───────────────────────────────────────
|
|
67
|
+
case "EntityNotFound":
|
|
68
|
+
return `no entity ${short(args[0])} — it may have been deleted, or have expired`
|
|
69
|
+
case "EntityExpired":
|
|
70
|
+
return `entity ${short(args[0])} expired at block ${String(args[1])}`
|
|
71
|
+
case "NotOwner":
|
|
72
|
+
return `entity ${short(args[0])} is owned by ${String(args[2])}, not ${String(args[1])}`
|
|
73
|
+
case "ReadOnlyEntity":
|
|
74
|
+
return (
|
|
75
|
+
`entity ${short(args[0])} was created readonly, so its contents can never change. Its ` +
|
|
76
|
+
"expiry can still be extended, and it can be transferred or deleted"
|
|
77
|
+
)
|
|
78
|
+
case "ReservedCreationFlags":
|
|
79
|
+
return (
|
|
80
|
+
`creation flags 0b${Number(args[0] ?? 0)
|
|
81
|
+
.toString(2)
|
|
82
|
+
.padStart(8, "0")} set a reserved ` +
|
|
83
|
+
"bit; only readonly and permissionlessExtension are defined"
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
// ── expiry ───────────────────────────────────────────────────────────────
|
|
87
|
+
case "ExpiryDeadOnArrival":
|
|
88
|
+
return (
|
|
89
|
+
`the expiry resolves to block ${String(args[0])}, which is not after the current block ` +
|
|
90
|
+
`${String(args[1])}`
|
|
91
|
+
)
|
|
92
|
+
case "ExpiryNotExtended":
|
|
93
|
+
return (
|
|
94
|
+
`entity ${short(args[0])} already expires at block ${String(args[2])}, so extending it ` +
|
|
95
|
+
`to ${String(args[1])} would shorten its life`
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
// ── ownership ────────────────────────────────────────────────────────────
|
|
99
|
+
case "TransferToZeroAddress":
|
|
100
|
+
return `entity ${short(args[0])} cannot be transferred to the zero address`
|
|
101
|
+
case "TransferToSelf":
|
|
102
|
+
return `entity ${short(args[0])} is already owned by that account`
|
|
103
|
+
|
|
104
|
+
// ── batch framing ────────────────────────────────────────────────────────
|
|
105
|
+
case "EmptyBatch":
|
|
106
|
+
return "the batch has no operations"
|
|
107
|
+
case "InvalidOpType":
|
|
108
|
+
return `operation tag ${String(args[0])} is not one the engine knows`
|
|
109
|
+
case "NonCanonicalOperationData":
|
|
110
|
+
return (
|
|
111
|
+
`the payload for operation tag ${String(args[0])} is not its canonical encoding, so the ` +
|
|
112
|
+
"engine refused it rather than accept a second spelling of the same operation"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
default:
|
|
116
|
+
return undefined
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** A `bytes32` Ident32 cell as the name it holds — left-aligned, null-padded. */
|
|
121
|
+
function identName(raw: unknown): string {
|
|
122
|
+
if (typeof raw !== "string") return String(raw)
|
|
123
|
+
try {
|
|
124
|
+
// Cut at the first null rather than trimming with a regex: the padding is whatever follows
|
|
125
|
+
// the name, so everything before it is the name and nothing after it is. Written as an escape
|
|
126
|
+
// because a literal NUL byte in source is invisible to every reader after you.
|
|
127
|
+
return hexToString(raw as Hex).split("\u0000")[0] ?? ""
|
|
128
|
+
} catch {
|
|
129
|
+
return raw
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** An entity key, abbreviated */
|
|
134
|
+
function short(raw: unknown): string {
|
|
135
|
+
const text = String(raw)
|
|
136
|
+
return text.length > 18 ? `${text.slice(0, 10)}…${text.slice(-6)}` : text
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** A `bytes1` as something readable: the character it is, plus the byte it was. */
|
|
140
|
+
function printable(byte: string): string {
|
|
141
|
+
const code = Number.parseInt(byte.replace(/^0x/, ""), 16)
|
|
142
|
+
if (!Number.isFinite(code)) return `byte ${byte}`
|
|
143
|
+
const char = String.fromCharCode(code)
|
|
144
|
+
return code >= 0x21 && code <= 0x7e ? `"${char}" (${byte})` : `byte ${byte}`
|
|
145
|
+
}
|
package/dist/chains-BifaY04V.cjs
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
//#region rolldown:runtime
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __export = (all) => {
|
|
4
|
-
let target = {};
|
|
5
|
-
for (var name in all) __defProp(target, name, {
|
|
6
|
-
get: all[name],
|
|
7
|
-
enumerable: true
|
|
8
|
-
});
|
|
9
|
-
return target;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
//#endregion
|
|
13
|
-
let viem = require("viem");
|
|
14
|
-
|
|
15
|
-
//#region src/chains/braga.ts
|
|
16
|
-
const braga = (0, viem.defineChain)({
|
|
17
|
-
id: 60138453102,
|
|
18
|
-
name: "Braga",
|
|
19
|
-
network: "braga",
|
|
20
|
-
nativeCurrency: {
|
|
21
|
-
name: "Golem",
|
|
22
|
-
symbol: "GLM",
|
|
23
|
-
decimals: 18
|
|
24
|
-
},
|
|
25
|
-
rpcUrls: { default: {
|
|
26
|
-
http: ["https://braga.hoodi.arkiv.network/rpc"],
|
|
27
|
-
webSocket: ["wss://braga.hoodi.arkiv.network/rpc/ws"]
|
|
28
|
-
} },
|
|
29
|
-
blockExplorers: { default: {
|
|
30
|
-
name: "Braga Arkiv Explorer",
|
|
31
|
-
url: "https://explorer.braga.hoodi.arkiv.network",
|
|
32
|
-
apiUrl: "https://explorer.braga.hoodi.arkiv.network/api"
|
|
33
|
-
} },
|
|
34
|
-
testnet: true
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
//#endregion
|
|
38
|
-
//#region src/chains/kaolin.ts
|
|
39
|
-
/**
|
|
40
|
-
* @deprecated The kaolin network is getting removed on may 15th 2026. Migration guide: https://docs.arkiv.network/networks/migrate-from-kaolin/
|
|
41
|
-
*/
|
|
42
|
-
const kaolin = (0, viem.defineChain)({
|
|
43
|
-
id: 60138453025,
|
|
44
|
-
name: "Kaolin",
|
|
45
|
-
network: "kaolin",
|
|
46
|
-
nativeCurrency: {
|
|
47
|
-
name: "Ethereum",
|
|
48
|
-
symbol: "ETH",
|
|
49
|
-
decimals: 18
|
|
50
|
-
},
|
|
51
|
-
rpcUrls: { default: {
|
|
52
|
-
http: ["https://kaolin.hoodi.arkiv.network/rpc"],
|
|
53
|
-
webSocket: ["wss://kaolin.hoodi.arkiv.network/rpc/ws"]
|
|
54
|
-
} },
|
|
55
|
-
blockExplorers: { default: {
|
|
56
|
-
name: "Kaolin Arkiv Explorer",
|
|
57
|
-
url: "https://explorer.kaolin.hoodi.arkiv.network",
|
|
58
|
-
apiUrl: "https://explorer.kaolin.hoodi.arkiv.network/api"
|
|
59
|
-
} },
|
|
60
|
-
testnet: true
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
//#endregion
|
|
64
|
-
//#region src/chains/localhost.ts
|
|
65
|
-
const localhost = (0, viem.defineChain)({
|
|
66
|
-
id: 1337,
|
|
67
|
-
name: "Localhost",
|
|
68
|
-
nativeCurrency: {
|
|
69
|
-
decimals: 18,
|
|
70
|
-
name: "Ether",
|
|
71
|
-
symbol: "ETH"
|
|
72
|
-
},
|
|
73
|
-
rpcUrls: { default: { http: ["http://127.0.0.1:8545"] } }
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
//#endregion
|
|
77
|
-
//#region src/chains/index.ts
|
|
78
|
-
var chains_exports = /* @__PURE__ */ __export({
|
|
79
|
-
braga: () => braga,
|
|
80
|
-
kaolin: () => kaolin,
|
|
81
|
-
localhost: () => localhost
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
//#endregion
|
|
85
|
-
Object.defineProperty(exports, 'braga', {
|
|
86
|
-
enumerable: true,
|
|
87
|
-
get: function () {
|
|
88
|
-
return braga;
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
Object.defineProperty(exports, 'chains_exports', {
|
|
92
|
-
enumerable: true,
|
|
93
|
-
get: function () {
|
|
94
|
-
return chains_exports;
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
Object.defineProperty(exports, 'kaolin', {
|
|
98
|
-
enumerable: true,
|
|
99
|
-
get: function () {
|
|
100
|
-
return kaolin;
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
Object.defineProperty(exports, 'localhost', {
|
|
104
|
-
enumerable: true,
|
|
105
|
-
get: function () {
|
|
106
|
-
return localhost;
|
|
107
|
-
}
|
|
108
|
-
});
|