@arkiv-network/sdk 0.7.0 → 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 +39 -77
- 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 +675 -357
- package/dist/index.d.cts +251 -203
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +251 -203
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +626 -355
- 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 -149
- package/dist/query/index.d.cts +5 -3
- package/dist/query/index.d.ts +5 -3
- package/dist/query/index.js +6 -137
- 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 +4 -1
- package/dist/types/index.d.cts +7 -2
- package/dist/types/index.d.ts +7 -2
- package/dist/types/index.js +4 -1
- 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 +8 -8
- package/src/actions/wallet/createEntity.ts +104 -26
- package/src/actions/wallet/deleteEntity.ts +2 -3
- package/src/actions/wallet/extendEntity.ts +39 -16
- package/src/actions/wallet/mutateEntities.test.ts +76 -0
- package/src/actions/wallet/mutateEntities.ts +29 -74
- 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 +91 -95
- package/src/consts.ts +2 -1
- 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 +33 -28
- package/src/index.ts +6 -0
- package/src/query/engine.ts +59 -134
- 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 +62 -44
- package/src/types/events.ts +64 -23
- package/src/types/index.ts +20 -16
- package/src/types/rpcSchema.ts +70 -33
- package/src/utils/arkivTransactions.test.ts +681 -38
- package/src/utils/arkivTransactions.ts +249 -104
- 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 +111 -29
- package/src/utils/expirationTime.ts +114 -10
- package/src/utils/logger.ts +2 -2
- package/src/utils/payload.ts +4 -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-AUoL-v42.cjs +0 -18
- package/dist/consts-BV4PR-de.js +0 -7
- package/dist/consts-BV4PR-de.js.map +0 -1
- package/dist/entity-B6g_EPm1.d.cts +0 -382
- package/dist/entity-B6g_EPm1.d.cts.map +0 -1
- package/dist/entity-qoLMAuuk.d.ts +0 -382
- package/dist/entity-qoLMAuuk.d.ts.map +0 -1
- package/dist/index-DdspxNAA.d.ts +0 -481
- package/dist/index-DdspxNAA.d.ts.map +0 -1
- package/dist/index-Ds9dwqb5.d.cts +0 -481
- package/dist/index-Ds9dwqb5.d.cts.map +0 -1
- package/dist/payload-B2kFJyah.d.ts +0 -6
- package/dist/payload-B2kFJyah.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-Claf2jUO.js +0 -13
- package/dist/payload-Claf2jUO.js.map +0 -1
- package/dist/payload-DpA5PA-w.cjs +0 -23
- package/dist/query/index.js.map +0 -1
- package/dist/queryBuilder-D2uwP9jI.js +0 -704
- package/dist/queryBuilder-D2uwP9jI.js.map +0 -1
- package/dist/queryBuilder-UW2MCaX4.cjs +0 -792
- 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 -119
- package/src/actions/wallet/updateEntity.ts +0 -60
- package/src/chains/braga.ts +0 -26
- package/src/chains/kaolin.ts +0 -29
- package/src/query/engine.test.ts +0 -526
- 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 -210
- package/src/types/attributes.ts +0 -16
- package/src/utils/validation.test.ts +0 -60
- package/src/utils/validation.ts +0 -32
- /package/dist/{types-H-TSmRpm.js → types-Bx1EKe0v.js} +0 -0
- /package/dist/{types-o3zWarRp.cjs → types-CKPddlfS.cjs} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
const require_chains = require('./chains-
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
require('./
|
|
5
|
-
const
|
|
1
|
+
const require_chains = require('./chains-BYRTTipa.cjs');
|
|
2
|
+
const require_attr = require('./attr-BvxHN99W.cjs');
|
|
3
|
+
const require_queryBuilder = require('./queryBuilder-BXDvX1K_.cjs');
|
|
4
|
+
const require_errors = require('./errors-D-eJkGVc.cjs');
|
|
5
|
+
const require_flags = require('./flags-Ct8k0gpB.cjs');
|
|
6
|
+
const require_entity = require('./entity-B0t6sN7F.cjs');
|
|
7
|
+
const require_expiry = require('./expiry-BUYIXTGb.cjs');
|
|
8
|
+
const require_entity$1 = require('./entity-wfBnZd91.cjs');
|
|
9
|
+
require('./types-CKPddlfS.cjs');
|
|
10
|
+
const require_payload = require('./payload-Bnw1hrvb.cjs');
|
|
6
11
|
let viem = require("viem");
|
|
12
|
+
let viem_actions = require("viem/actions");
|
|
7
13
|
|
|
8
14
|
//#region src/actions/public/getBlockTiming.ts
|
|
9
15
|
const logger$9 = require_queryBuilder.getLogger("actions:public:get-block-timing");
|
|
@@ -22,33 +28,26 @@ async function getBlockTiming(client) {
|
|
|
22
28
|
|
|
23
29
|
//#endregion
|
|
24
30
|
//#region src/actions/public/getEntity.ts
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
expiration: true,
|
|
42
|
-
owner: true,
|
|
43
|
-
creator: true,
|
|
44
|
-
createdAtBlock: true,
|
|
45
|
-
lastModifiedAtBlock: true,
|
|
46
|
-
transactionIndexInBlock: true,
|
|
47
|
-
operationIndexInTransaction: true
|
|
48
|
-
} }]
|
|
31
|
+
/**
|
|
32
|
+
* Reads one entity by key, with every field selected.
|
|
33
|
+
*
|
|
34
|
+
* Returns a {@link FullEntity} rather than an {@link Entity}: the selection is fixed at `"*"`, so
|
|
35
|
+
* every field is populated and none of them needs a `?` at the call site. The bare `Entity` type
|
|
36
|
+
* has every field optional because a `select()` result carries only what it asked for.
|
|
37
|
+
*
|
|
38
|
+
* @throws {InvalidValueError} If the key is not 32 bytes.
|
|
39
|
+
* @throws {NoEntityFoundError} If no live entity has that key — it never existed, or it was
|
|
40
|
+
* deleted or has expired.
|
|
41
|
+
*/
|
|
42
|
+
async function getEntity(client, entityKey) {
|
|
43
|
+
const { entities } = await require_queryBuilder.runQuery(client, {
|
|
44
|
+
query: require_queryBuilder.eq("$key", require_attr.key(entityKey)).toString(),
|
|
45
|
+
select: require_queryBuilder.toRpcSelect("*"),
|
|
46
|
+
limit: 1
|
|
49
47
|
});
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
const entity = entities[0];
|
|
49
|
+
if (entity === void 0) throw new require_queryBuilder.NoEntityFoundError(entityKey);
|
|
50
|
+
return entity;
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
//#endregion
|
|
@@ -61,144 +60,360 @@ async function getEntityCount(client) {
|
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
//#endregion
|
|
64
|
-
//#region src/
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
63
|
+
//#region src/entity/operations.ts
|
|
64
|
+
/**
|
|
65
|
+
* The one external entry point. A transaction is an ordered, **atomic** batch of entity operations:
|
|
66
|
+
* all of them apply or none do, operation *n+1* observes operation *n*'s effects, and each applied
|
|
67
|
+
* operation emits one event.
|
|
68
|
+
*/
|
|
69
|
+
const EXECUTE_ABI = (0, viem.parseAbi)(["function execute((uint8 operation, bytes operationData)[] ops) external returns (bytes32[] keys)"]);
|
|
70
|
+
/**
|
|
71
|
+
* The engine's one read-only view: an owner's entity-minting nonce, which is the input
|
|
72
|
+
* {@link predictEntityKey} needs and the only part of the derivation the caller cannot know.
|
|
73
|
+
*
|
|
74
|
+
* It is a `view` on the same address `execute` is called on, so it answers over `eth_call` without
|
|
75
|
+
* a transaction.
|
|
76
|
+
*/
|
|
77
|
+
const ENTITY_NONCE_ABI = (0, viem.parseAbi)(["function entityNonce(address owner) external view returns (uint64)"]);
|
|
78
|
+
/**
|
|
79
|
+
* The shared attribute shape, used by `create` (attributes) and `patch` (mutations). Written out
|
|
80
|
+
* once and reused by every payload that carries attributes.
|
|
81
|
+
*/
|
|
82
|
+
const ATTRIBUTE_TUPLE = "(bytes32 name, uint8 typeId, bytes value)[]";
|
|
83
|
+
/**
|
|
84
|
+
* The payload struct for each operation tag. `operationData` is `abi.encode` of the struct the tag
|
|
85
|
+
* selects — a tagged union, so a new operation is additive rather than a change to `execute`.
|
|
86
|
+
*/
|
|
87
|
+
const PAYLOAD_PARAMS = {
|
|
88
|
+
[require_expiry.OperationType.Create]: (0, viem.parseAbiParameters)(`(uint128 salt, uint64 expiresAt, uint64 minLifetime, uint8 creationFlags, ${ATTRIBUTE_TUPLE} attributes)`),
|
|
89
|
+
[require_expiry.OperationType.Patch]: (0, viem.parseAbiParameters)(`(bytes32 entityKey, ${ATTRIBUTE_TUPLE} mutations)`),
|
|
90
|
+
[require_expiry.OperationType.ExtendExpiry]: (0, viem.parseAbiParameters)("(bytes32 entityKey, uint64 expiresAt, uint64 minLifetime)"),
|
|
91
|
+
[require_expiry.OperationType.TransferOwnership]: (0, viem.parseAbiParameters)("(bytes32 entityKey, address newOwner)"),
|
|
92
|
+
[require_expiry.OperationType.Delete]: (0, viem.parseAbiParameters)("(bytes32 entityKey)")
|
|
93
|
+
};
|
|
94
|
+
/** Creates an entity. The key is derived by the engine; predict it with `predictEntityKey`. */
|
|
95
|
+
function createOperation({ salt, expiry, creationFlags, attributes }) {
|
|
96
|
+
return {
|
|
97
|
+
operation: require_expiry.OperationType.Create,
|
|
98
|
+
operationData: (0, viem.encodeAbiParameters)(PAYLOAD_PARAMS[require_expiry.OperationType.Create], [{
|
|
99
|
+
salt,
|
|
100
|
+
expiresAt: expiry.expiresAt,
|
|
101
|
+
minLifetime: expiry.minLifetime,
|
|
102
|
+
creationFlags,
|
|
103
|
+
attributes
|
|
104
|
+
}])
|
|
88
105
|
};
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
106
|
+
}
|
|
107
|
+
/** Applies a set of mutations to an existing entity. Tombstones unset attributes. */
|
|
108
|
+
function patchOperation({ entityKey, mutations }) {
|
|
109
|
+
return {
|
|
110
|
+
operation: require_expiry.OperationType.Patch,
|
|
111
|
+
operationData: (0, viem.encodeAbiParameters)(PAYLOAD_PARAMS[require_expiry.OperationType.Patch], [{
|
|
112
|
+
entityKey,
|
|
113
|
+
mutations
|
|
114
|
+
}])
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/** Pushes an entity's expiry further out. Extending is allowed; shortening reverts. */
|
|
118
|
+
function extendExpiryOperation({ entityKey, expiry }) {
|
|
119
|
+
return {
|
|
120
|
+
operation: require_expiry.OperationType.ExtendExpiry,
|
|
121
|
+
operationData: (0, viem.encodeAbiParameters)(PAYLOAD_PARAMS[require_expiry.OperationType.ExtendExpiry], [{
|
|
122
|
+
entityKey,
|
|
123
|
+
expiresAt: expiry.expiresAt,
|
|
124
|
+
minLifetime: expiry.minLifetime
|
|
125
|
+
}])
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/** Hands an entity to a new owner. */
|
|
129
|
+
function transferOwnershipOperation({ entityKey, newOwner }) {
|
|
130
|
+
return {
|
|
131
|
+
operation: require_expiry.OperationType.TransferOwnership,
|
|
132
|
+
operationData: (0, viem.encodeAbiParameters)(PAYLOAD_PARAMS[require_expiry.OperationType.TransferOwnership], [{
|
|
133
|
+
entityKey,
|
|
134
|
+
newOwner
|
|
135
|
+
}])
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/** Deletes an entity before its expiry. */
|
|
139
|
+
function deleteOperation({ entityKey }) {
|
|
93
140
|
return {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
blockNumber: BigInt(result.blockNumber)
|
|
141
|
+
operation: require_expiry.OperationType.Delete,
|
|
142
|
+
operationData: (0, viem.encodeAbiParameters)(PAYLOAD_PARAMS[require_expiry.OperationType.Delete], [{ entityKey }])
|
|
97
143
|
};
|
|
98
144
|
}
|
|
99
145
|
|
|
100
146
|
//#endregion
|
|
101
|
-
//#region src/actions/public/
|
|
102
|
-
const logger$8 = require_queryBuilder.getLogger("actions:public:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
147
|
+
//#region src/actions/public/getEntityNonce.ts
|
|
148
|
+
const logger$8 = require_queryBuilder.getLogger("actions:public:get-entity-nonce");
|
|
149
|
+
/**
|
|
150
|
+
* Reads an owner's entity-minting nonce — how many entities that account has created.
|
|
151
|
+
*
|
|
152
|
+
* This is not the account's transaction nonce. The engine keeps a separate counter per creator and
|
|
153
|
+
* mixes it into every key it mints, which is what makes two identical creates from one account land
|
|
154
|
+
* on different keys.
|
|
155
|
+
*
|
|
156
|
+
* @param owner - The account whose nonce to read.
|
|
157
|
+
* @returns The number of entities `owner` has created so far, which is the nonce its next create
|
|
158
|
+
* will use.
|
|
159
|
+
*/
|
|
160
|
+
async function getEntityNonce(client, owner) {
|
|
161
|
+
const nonce = await (0, viem_actions.readContract)(client, {
|
|
162
|
+
address: require_expiry.ARKIV_ADDRESS,
|
|
163
|
+
abi: ENTITY_NONCE_ABI,
|
|
164
|
+
functionName: "entityNonce",
|
|
165
|
+
args: [owner]
|
|
166
|
+
});
|
|
167
|
+
logger$8("entity nonce of %s is %s", owner, nonce);
|
|
168
|
+
return nonce;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region src/actions/public/predictEntityKeys.ts
|
|
173
|
+
/**
|
|
174
|
+
* Works out the keys an account's next creates will be given, before sending them.
|
|
175
|
+
*
|
|
176
|
+
* A key is `keccak256(chainId ++ registry ++ owner ++ nonce ++ salt)`. Everything but the nonce is
|
|
177
|
+
* known to the caller, and the nonce is read here — so a batch can reference a key it is about to
|
|
178
|
+
* mint, storing it as a `key` attribute on a sibling entity created in the same transaction.
|
|
179
|
+
*
|
|
180
|
+
* Each key arrives paired with its salt, and the create must be given that salt: a create left to
|
|
181
|
+
* pick its own salt picks a random one, which mints a different key.
|
|
182
|
+
*
|
|
183
|
+
* The prediction is valid only while nothing else from this owner is in flight. Every create that
|
|
184
|
+
* lands first takes the nonce with it and moves these keys. For a key you can rely on
|
|
185
|
+
* unconditionally, read it back from the create instead — `createEntity` and `mutateEntities`
|
|
186
|
+
* report the keys the engine actually minted.
|
|
187
|
+
*
|
|
188
|
+
* @param parameters - Owner, and either a count or the salts. {@link PredictEntityKeysParameters}
|
|
189
|
+
* @returns One `{ key, salt }` pair per create, in batch order. {@link PredictEntityKeysReturnType}
|
|
190
|
+
*
|
|
191
|
+
* @example A batch whose second entity points at its first.
|
|
192
|
+
* import { key } from "@arkiv-network/sdk/attr"
|
|
193
|
+
*
|
|
194
|
+
* const [parent, child] = await client.predictEntityKeys({ owner: account.address, count: 2 })
|
|
195
|
+
* await wallet.mutateEntities({
|
|
196
|
+
* creates: [
|
|
197
|
+
* { payload, contentType, expires, salt: parent.salt },
|
|
198
|
+
* {
|
|
199
|
+
* payload,
|
|
200
|
+
* contentType,
|
|
201
|
+
* expires,
|
|
202
|
+
* salt: child.salt,
|
|
203
|
+
* attributes: { parent: key(parent.key) },
|
|
204
|
+
* },
|
|
205
|
+
* ],
|
|
206
|
+
* })
|
|
207
|
+
*/
|
|
208
|
+
async function predictEntityKeys(client, { owner, count, salts }) {
|
|
209
|
+
const resolvedSalts = resolveSalts(count, salts);
|
|
210
|
+
const chainId = client.chain?.id ?? await (0, viem_actions.getChainId)(client);
|
|
211
|
+
const nonce = await getEntityNonce(client, owner);
|
|
212
|
+
return resolvedSalts.map((salt, index) => ({
|
|
213
|
+
key: require_entity$1.predictEntityKey({
|
|
214
|
+
owner,
|
|
215
|
+
nonce: nonce + BigInt(index),
|
|
216
|
+
salt,
|
|
217
|
+
chainId
|
|
218
|
+
}),
|
|
219
|
+
salt
|
|
220
|
+
}));
|
|
221
|
+
}
|
|
222
|
+
/** The salts to derive from: the ones given, or `count` fresh random ones. */
|
|
223
|
+
function resolveSalts(count, salts) {
|
|
224
|
+
if (salts !== void 0) {
|
|
225
|
+
if (salts.length === 0) throw new Error("predictEntityKeys: `salts` is empty — there is nothing to predict");
|
|
226
|
+
return salts.map(require_entity$1.validateSalt);
|
|
227
|
+
}
|
|
228
|
+
if (count === void 0) throw new Error("predictEntityKeys: pass either `count` or `salts`");
|
|
229
|
+
if (!Number.isInteger(count) || count <= 0) throw new Error(`predictEntityKeys: \`count\` must be a positive whole number, got ${count}`);
|
|
230
|
+
return Array.from({ length: count }, () => require_entity$1.randomSalt());
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
//#endregion
|
|
234
|
+
//#region src/actions/public/query.ts
|
|
235
|
+
/**
|
|
236
|
+
* Runs a single query and returns one page, with no builder in between.
|
|
237
|
+
*
|
|
238
|
+
* Takes either an {@link Expression} or a raw query string. The string form is an escape hatch for
|
|
239
|
+
* a query built elsewhere — it goes to the node exactly as written, with none of the name, type or
|
|
240
|
+
* operator checks the expression combinators apply.
|
|
241
|
+
*
|
|
242
|
+
* @throws {QueryError} If the node rejects the query.
|
|
243
|
+
*/
|
|
244
|
+
function query(client, query$1, options = {}) {
|
|
245
|
+
return require_queryBuilder.runQuery(client, {
|
|
246
|
+
query: query$1.toString(),
|
|
247
|
+
select: require_queryBuilder.toRpcSelect(options.select),
|
|
248
|
+
limit: options.limit,
|
|
249
|
+
cursor: options.cursor,
|
|
250
|
+
atBlock: options.atBlock
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
//#endregion
|
|
255
|
+
//#region src/actions/public/watchEntityEvents.ts
|
|
256
|
+
const logger$7 = require_queryBuilder.getLogger("actions:public:watch-entity-events");
|
|
257
|
+
/**
|
|
258
|
+
* How often to poll, when the caller does not say.
|
|
259
|
+
*
|
|
260
|
+
* Half a block: fast enough that an event is never a whole block stale, slow enough not to hammer
|
|
261
|
+
* the node. viem's own default is derived from a 12-second Ethereum block and is far too slow here.
|
|
262
|
+
*/
|
|
263
|
+
const DEFAULT_POLLING_INTERVAL = require_expiry.BLOCK_TIME * 1e3 / 2;
|
|
264
|
+
/**
|
|
265
|
+
* Watches entity events, calling the handlers you pass as they arrive.
|
|
266
|
+
*
|
|
267
|
+
* Every event here is decoded from a log the Arkiv operation address emitted, and carries the
|
|
268
|
+
* block, transaction and log index it came from — so consuming them in order replays exactly what
|
|
269
|
+
* the engine did.
|
|
270
|
+
*
|
|
271
|
+
* @param parameters - Handlers and options. {@link WatchEntityEventsParameters}
|
|
272
|
+
* @returns A function that stops the watcher.
|
|
273
|
+
*
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* import { createPublicClient } from "@arkiv-network/sdk"
|
|
277
|
+
* import { cheesecake } from "@arkiv-network/sdk/chains"
|
|
278
|
+
* import { http } from "viem"
|
|
279
|
+
*
|
|
280
|
+
* const client = createPublicClient({ chain: cheesecake, transport: http() })
|
|
281
|
+
*
|
|
282
|
+
* const unwatch = client.watchEntityEvents({
|
|
283
|
+
* onEntityCreated: ({ entityKey, owner, expiresAt }) =>
|
|
284
|
+
* console.log("created", entityKey, "by", owner, "until block", expiresAt),
|
|
285
|
+
* onEntityDeleted: ({ entityKey }) => console.log("deleted", entityKey),
|
|
286
|
+
* onError: (error) => console.error(error),
|
|
287
|
+
* })
|
|
288
|
+
*
|
|
289
|
+
* unwatch()
|
|
290
|
+
*/
|
|
291
|
+
function watchEntityEvents(client, parameters) {
|
|
292
|
+
const { onEntityCreated, onEntityPatched, onExpiryExtended, onOwnershipTransferred, onEntityDeleted, onEvent, onError, fromBlock, pollingInterval = DEFAULT_POLLING_INTERVAL } = parameters;
|
|
293
|
+
const publicClient = client;
|
|
294
|
+
const reportError = onError ?? logToConsole;
|
|
295
|
+
function emit(event) {
|
|
296
|
+
deliver(onEvent, event);
|
|
297
|
+
switch (event.type) {
|
|
298
|
+
case "EntityCreated":
|
|
299
|
+
deliver(onEntityCreated, event);
|
|
300
|
+
break;
|
|
301
|
+
case "EntityPatched":
|
|
302
|
+
deliver(onEntityPatched, event);
|
|
303
|
+
break;
|
|
304
|
+
case "ExpiryExtended":
|
|
305
|
+
deliver(onExpiryExtended, event);
|
|
306
|
+
break;
|
|
307
|
+
case "OwnershipTransferred":
|
|
308
|
+
deliver(onOwnershipTransferred, event);
|
|
309
|
+
break;
|
|
310
|
+
case "EntityDeleted":
|
|
311
|
+
deliver(onEntityDeleted, event);
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Runs one handler, keeping its failure to itself.
|
|
317
|
+
*
|
|
318
|
+
* A handler that throws is the consumer's problem, not the watcher's: letting it escape would
|
|
319
|
+
* reject the poll, drop the rest of the batch, and take down every other handler with it.
|
|
320
|
+
*/
|
|
321
|
+
function deliver(handler, event) {
|
|
322
|
+
if (handler === void 0) return;
|
|
323
|
+
try {
|
|
324
|
+
handler(event);
|
|
325
|
+
} catch (error) {
|
|
326
|
+
reportError(asError(error));
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return publicClient.watchEvent({
|
|
330
|
+
address: require_expiry.ARKIV_ADDRESS,
|
|
331
|
+
events: require_entity$1.ENTITY_EVENTS_ABI,
|
|
332
|
+
pollingInterval,
|
|
333
|
+
...fromBlock !== void 0 && { fromBlock },
|
|
116
334
|
onLogs: (logs) => {
|
|
117
|
-
logger$
|
|
335
|
+
logger$7("logs %o", logs);
|
|
118
336
|
for (const log of logs) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
cost: event.args.cost
|
|
132
|
-
});
|
|
133
|
-
break;
|
|
134
|
-
case "ArkivEntityUpdated":
|
|
135
|
-
onEntityUpdated?.({
|
|
136
|
-
entityKey: (0, viem.toHex)(event.args.entityKey, { size: 32 }),
|
|
137
|
-
owner: event.args.ownerAddress,
|
|
138
|
-
oldExpirationBlock: Number(event.args.oldExpirationBlock),
|
|
139
|
-
newExpirationBlock: Number(event.args.newExpirationBlock),
|
|
140
|
-
cost: event.args.cost
|
|
141
|
-
});
|
|
142
|
-
break;
|
|
143
|
-
case "ArkivEntityDeleted":
|
|
144
|
-
onEntityDeleted?.({
|
|
145
|
-
entityKey: (0, viem.toHex)(event.args.entityKey, { size: 32 }),
|
|
146
|
-
owner: event.args.ownerAddress
|
|
147
|
-
});
|
|
148
|
-
break;
|
|
149
|
-
case "ArkivEntityBTLExtended":
|
|
150
|
-
onEntityExpiresInExtended?.({
|
|
151
|
-
entityKey: (0, viem.toHex)(event.args.entityKey, { size: 32 }),
|
|
152
|
-
owner: event.args.ownerAddress,
|
|
153
|
-
oldExpirationBlock: Number(event.args.oldExpirationBlock),
|
|
154
|
-
newExpirationBlock: Number(event.args.newExpirationBlock),
|
|
155
|
-
cost: event.args.cost
|
|
156
|
-
});
|
|
157
|
-
break;
|
|
158
|
-
case "ArkivEntityExpired":
|
|
159
|
-
onEntityExpired?.({
|
|
160
|
-
entityKey: (0, viem.toHex)(event.args.entityKey, { size: 32 }),
|
|
161
|
-
owner: event.args.ownerAddress
|
|
162
|
-
});
|
|
163
|
-
break;
|
|
164
|
-
case "ArkivEntityOwnerChanged":
|
|
165
|
-
onEntityOwnerChanged?.({
|
|
166
|
-
entityKey: (0, viem.toHex)(event.args.entityKey, { size: 32 }),
|
|
167
|
-
oldOwner: event.args.oldOwnerAddress,
|
|
168
|
-
newOwner: event.args.newOwnerAddress
|
|
169
|
-
});
|
|
170
|
-
break;
|
|
171
|
-
default:
|
|
172
|
-
console.warn("unknown event from subscribeEntityEvents", event);
|
|
173
|
-
break;
|
|
337
|
+
if (log.blockNumber === null || log.transactionHash === null || log.logIndex === null) continue;
|
|
338
|
+
const context = {
|
|
339
|
+
blockNumber: log.blockNumber,
|
|
340
|
+
transactionHash: log.transactionHash,
|
|
341
|
+
logIndex: log.logIndex
|
|
342
|
+
};
|
|
343
|
+
let event;
|
|
344
|
+
try {
|
|
345
|
+
event = toEntityEvent(log.topics, log.data, context);
|
|
346
|
+
} catch (error) {
|
|
347
|
+
reportError(asError(error));
|
|
348
|
+
continue;
|
|
174
349
|
}
|
|
350
|
+
emit(event);
|
|
175
351
|
}
|
|
176
352
|
},
|
|
177
|
-
onError: (error) =>
|
|
178
|
-
console.error("error from subscribeEntityEvents", error);
|
|
179
|
-
onError?.(error);
|
|
180
|
-
}
|
|
353
|
+
onError: (error) => reportError(error)
|
|
181
354
|
});
|
|
182
355
|
}
|
|
356
|
+
/** The fallback when no `onError` was given — see {@link WatchEntityEventsParameters.onError}. */
|
|
357
|
+
function logToConsole(error) {
|
|
358
|
+
console.error("watchEntityEvents error", error);
|
|
359
|
+
}
|
|
360
|
+
/** Handlers take an `Error`, and a `throw` can be anything. */
|
|
361
|
+
function asError(error) {
|
|
362
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Decodes one log into the {@link EntityEvent} it carries.
|
|
366
|
+
*
|
|
367
|
+
* @throws If the log does not decode against {@link ENTITY_EVENTS_ABI}.
|
|
368
|
+
*/
|
|
369
|
+
function toEntityEvent(topics, data, context) {
|
|
370
|
+
const decoded = (0, viem.decodeEventLog)({
|
|
371
|
+
abi: require_entity$1.ENTITY_EVENTS_ABI,
|
|
372
|
+
topics,
|
|
373
|
+
data
|
|
374
|
+
});
|
|
375
|
+
switch (decoded.eventName) {
|
|
376
|
+
case "EntityCreated": return {
|
|
377
|
+
type: "EntityCreated",
|
|
378
|
+
...context,
|
|
379
|
+
...decoded.args,
|
|
380
|
+
creationFlags: require_flags.decodeCreationFlags(decoded.args.creationFlags)
|
|
381
|
+
};
|
|
382
|
+
case "EntityPatched": return {
|
|
383
|
+
type: "EntityPatched",
|
|
384
|
+
...context,
|
|
385
|
+
...decoded.args
|
|
386
|
+
};
|
|
387
|
+
case "ExpiryExtended": return {
|
|
388
|
+
type: "ExpiryExtended",
|
|
389
|
+
...context,
|
|
390
|
+
...decoded.args
|
|
391
|
+
};
|
|
392
|
+
case "OwnershipTransferred": return {
|
|
393
|
+
type: "OwnershipTransferred",
|
|
394
|
+
...context,
|
|
395
|
+
...decoded.args
|
|
396
|
+
};
|
|
397
|
+
case "EntityDeleted": return {
|
|
398
|
+
type: "EntityDeleted",
|
|
399
|
+
...context,
|
|
400
|
+
...decoded.args
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
}
|
|
183
404
|
|
|
184
405
|
//#endregion
|
|
185
406
|
//#region src/clients/decorators/arkivPublic.ts
|
|
186
407
|
function publicArkivActions(client) {
|
|
187
408
|
return {
|
|
188
|
-
getEntity: (key) => getEntity(client, key),
|
|
409
|
+
getEntity: (key$1) => getEntity(client, key$1),
|
|
189
410
|
query: (rawQuery, queryOptions) => query(client, rawQuery, queryOptions),
|
|
190
|
-
buildQuery: () => new require_queryBuilder.QueryBuilder(client),
|
|
191
411
|
select: (selection) => new require_queryBuilder.SelectQueryBuilder(client, selection),
|
|
192
412
|
getBlockTiming: () => getBlockTiming(client),
|
|
193
413
|
getEntityCount: () => getEntityCount(client),
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
onEntityUpdated,
|
|
198
|
-
onEntityDeleted,
|
|
199
|
-
onEntityExpired,
|
|
200
|
-
onEntityExpiresInExtended
|
|
201
|
-
}, pollingInterval, fromBlock)
|
|
414
|
+
getEntityNonce: (owner) => getEntityNonce(client, owner),
|
|
415
|
+
predictEntityKeys: (parameters) => predictEntityKeys(client, parameters),
|
|
416
|
+
watchEntityEvents: (parameters) => watchEntityEvents(client, parameters)
|
|
202
417
|
};
|
|
203
418
|
}
|
|
204
419
|
|
|
@@ -209,201 +424,278 @@ function publicArkivActions(client) {
|
|
|
209
424
|
*
|
|
210
425
|
* - Docs: https://docs.arkiv.network/ts-sdk/clients/public
|
|
211
426
|
*
|
|
212
|
-
* A Public Client is an interface to "public" [Ethereum JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc/), [Arkiv JSON-RPC API](https://docs.arkiv.network/json-rpc/), and [
|
|
427
|
+
* A Public Client is an interface to "public" [Ethereum JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc/), [Arkiv JSON-RPC API](https://docs.arkiv.network/json-rpc/), and [Cheesecake JSON-RPC API](https://rpc.cheesecake.db-chain.devnet.gobas.me) methods such as retrieving block numbers, transactions, reading from smart contracts, etc through [Public Actions](/docs/actions/public/introduction).
|
|
213
428
|
*
|
|
214
429
|
* @param parameters - Configuration object for the public client (chain, transport, etc.)
|
|
215
430
|
* @returns A Arkiv Public Client. {@link PublicArkivClient}
|
|
216
431
|
*
|
|
217
432
|
* @example
|
|
218
|
-
* import { createPublicClient
|
|
219
|
-
* import {
|
|
433
|
+
* import { createPublicClient } from "@arkiv-network/sdk"
|
|
434
|
+
* import { cheesecake } from "@arkiv-network/sdk/chains"
|
|
435
|
+
* import { http } from "viem"
|
|
220
436
|
*
|
|
221
437
|
* const client = createPublicClient({
|
|
222
|
-
* chain:
|
|
438
|
+
* chain: cheesecake,
|
|
223
439
|
* transport: http(),
|
|
224
440
|
* })
|
|
225
441
|
*/
|
|
226
442
|
function createPublicClient(parameters) {
|
|
227
|
-
const { key = "public", name = "Public Client" } = parameters;
|
|
443
|
+
const { key: key$1 = "public", name = "Public Client" } = parameters;
|
|
228
444
|
return (0, viem.createClient)({
|
|
229
445
|
...parameters,
|
|
230
|
-
key,
|
|
446
|
+
key: key$1,
|
|
231
447
|
name
|
|
232
448
|
}).extend(viem.publicActions).extend(publicArkivActions);
|
|
233
449
|
}
|
|
234
450
|
|
|
235
451
|
//#endregion
|
|
236
|
-
//#region src/utils/
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
452
|
+
//#region src/utils/revert.ts
|
|
453
|
+
/**
|
|
454
|
+
* Turns a decoded engine revert into a sentence that says what to change.
|
|
455
|
+
*
|
|
456
|
+
* viem decodes the error and then renders it positionally — `Ident32InvalidByte(uint256 position,
|
|
457
|
+
* bytes1 value)` arrives as `(5, 0x41)`, which is the right data and no help at all. The engine's
|
|
458
|
+
* errors carry enough to name the actual problem, so this spends the args rather than printing
|
|
459
|
+
* them.
|
|
460
|
+
*
|
|
461
|
+
* @param error - Anything thrown by a write action.
|
|
462
|
+
* @returns The explanation, or `undefined` if this was not a decodable engine revert — in which
|
|
463
|
+
* case the caller should fall back to whatever the transport said.
|
|
464
|
+
*/
|
|
465
|
+
function describeEntityRevert(error) {
|
|
466
|
+
if (!(error instanceof viem.BaseError)) return void 0;
|
|
467
|
+
const reverted = error.walk((e) => e instanceof viem.ContractFunctionRevertedError);
|
|
468
|
+
if (!(reverted instanceof viem.ContractFunctionRevertedError)) return void 0;
|
|
469
|
+
const name = reverted.data?.errorName;
|
|
470
|
+
if (name === void 0) return void 0;
|
|
471
|
+
return explain(name, reverted.data?.args ?? []) ?? `the engine rejected the batch with ${name}`;
|
|
250
472
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
return null;
|
|
259
|
-
}
|
|
260
|
-
return brotli;
|
|
261
|
-
}
|
|
262
|
-
async function compress(data) {
|
|
263
|
-
logger$7("Compressing data size %d", data.length);
|
|
264
|
-
if (isNode) {
|
|
265
|
-
const zlibModule = await getZlib();
|
|
266
|
-
if (zlibModule) try {
|
|
267
|
-
const buffer = Buffer.from(data);
|
|
268
|
-
const compressed = zlibModule.brotliCompressSync(buffer);
|
|
269
|
-
const result = new Uint8Array(compressed);
|
|
270
|
-
logger$7("Brotli compressed with zlib size %d", result.length);
|
|
271
|
-
return result;
|
|
272
|
-
} catch (error) {
|
|
273
|
-
console.warn("zlib compression failed, falling back to brotli-wasm", error);
|
|
473
|
+
/** The attribute-name charset, quoted the way an error message should read. */
|
|
474
|
+
const CHARSET = "\"A\"-\"Z\", \"a\"-\"z\", \"0\"-\"9\", \".\", \"-\" and \"_\", with a letter first";
|
|
475
|
+
function explain(name, args) {
|
|
476
|
+
switch (name) {
|
|
477
|
+
case "Ident32InvalidByte": {
|
|
478
|
+
const position = Number(args[0] ?? 0);
|
|
479
|
+
return `an attribute name holds ${printable(String(args[1] ?? "0x00"))} at byte ${position}, which is outside the name charset (${CHARSET})`;
|
|
274
480
|
}
|
|
481
|
+
case "Ident32Empty": return "an attribute name is empty";
|
|
482
|
+
case "SystemAttributeNotWritable": return `"${identName(args[0])}" is owned by the engine and cannot be written. Only $payload and \$contentType are yours to set`;
|
|
483
|
+
case "TombstoneInCreate": return `a create cannot unset "${identName(args[0])}" — nothing exists yet, so leave the name out instead`;
|
|
484
|
+
case "TombstoneValueNotEmpty": return `the tombstone for "${identName(args[0])}" carries a value; unsetting takes no value`;
|
|
485
|
+
case "InvalidValueType": return `"${identName(args[0])}" names type id ${String(args[1])}, which is not a known type`;
|
|
486
|
+
case "AttributesNotSorted": return "attributes must be strictly ascending by name, which also makes each name unique";
|
|
487
|
+
case "TooManyAttributes": return `${String(args[0])} attributes exceeds the limit of ${String(args[1])}`;
|
|
488
|
+
case "EmptyMutations": return `the patch of ${short(args[0])} has no mutations, so it would do nothing`;
|
|
489
|
+
case "EntityNotFound": return `no entity ${short(args[0])} — it may have been deleted, or have expired`;
|
|
490
|
+
case "EntityExpired": return `entity ${short(args[0])} expired at block ${String(args[1])}`;
|
|
491
|
+
case "NotOwner": return `entity ${short(args[0])} is owned by ${String(args[2])}, not ${String(args[1])}`;
|
|
492
|
+
case "ReadOnlyEntity": return `entity ${short(args[0])} was created readonly, so its contents can never change. Its expiry can still be extended, and it can be transferred or deleted`;
|
|
493
|
+
case "ReservedCreationFlags": return `creation flags 0b${Number(args[0] ?? 0).toString(2).padStart(8, "0")} set a reserved bit; only readonly and permissionlessExtension are defined`;
|
|
494
|
+
case "ExpiryDeadOnArrival": return `the expiry resolves to block ${String(args[0])}, which is not after the current block ${String(args[1])}`;
|
|
495
|
+
case "ExpiryNotExtended": return `entity ${short(args[0])} already expires at block ${String(args[2])}, so extending it to ${String(args[1])} would shorten its life`;
|
|
496
|
+
case "TransferToZeroAddress": return `entity ${short(args[0])} cannot be transferred to the zero address`;
|
|
497
|
+
case "TransferToSelf": return `entity ${short(args[0])} is already owned by that account`;
|
|
498
|
+
case "EmptyBatch": return "the batch has no operations";
|
|
499
|
+
case "InvalidOpType": return `operation tag ${String(args[0])} is not one the engine knows`;
|
|
500
|
+
case "NonCanonicalOperationData": return `the payload for operation tag ${String(args[0])} is not its canonical encoding, so the engine refused it rather than accept a second spelling of the same operation`;
|
|
501
|
+
default: return;
|
|
275
502
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
503
|
+
}
|
|
504
|
+
/** A `bytes32` Ident32 cell as the name it holds — left-aligned, null-padded. */
|
|
505
|
+
function identName(raw) {
|
|
506
|
+
if (typeof raw !== "string") return String(raw);
|
|
507
|
+
try {
|
|
508
|
+
return (0, viem.hexToString)(raw).split("\0")[0] ?? "";
|
|
509
|
+
} catch {
|
|
510
|
+
return raw;
|
|
280
511
|
}
|
|
281
|
-
const brotliCompressed = brotliInstance.compress(data);
|
|
282
|
-
logger$7("Brotli compressed with wasm size %d", brotliCompressed.length);
|
|
283
|
-
return brotliCompressed;
|
|
284
512
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
* Expiration on Arkiv is measured in blocks (1 block =
|
|
290
|
-
* 2 seconds), so the value must be a positive integer that is
|
|
291
|
-
* a multiple of the block time.
|
|
292
|
-
*
|
|
293
|
-
* @param expiresIn - The expiration in seconds.
|
|
294
|
-
* @throws {InvalidExpirationError} If the value is not a positive integer that
|
|
295
|
-
* is a multiple of the block time.
|
|
296
|
-
*/
|
|
297
|
-
function validateExpiresIn(expiresIn) {
|
|
298
|
-
if (!Number.isInteger(expiresIn) || expiresIn <= 0 || expiresIn % require_consts.BLOCK_TIME !== 0) throw new require_queryBuilder.InvalidExpirationError(expiresIn);
|
|
513
|
+
/** An entity key, abbreviated */
|
|
514
|
+
function short(raw) {
|
|
515
|
+
const text = String(raw);
|
|
516
|
+
return text.length > 18 ? `${text.slice(0, 10)}…${text.slice(-6)}` : text;
|
|
299
517
|
}
|
|
300
|
-
/**
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
* @throws {InvalidAttributeError} If the attribute has a non-integer numeric
|
|
306
|
-
* value.
|
|
307
|
-
*/
|
|
308
|
-
function validateAttribute(attribute) {
|
|
309
|
-
if (typeof attribute.value === "number" && !Number.isInteger(attribute.value)) throw new require_queryBuilder.InvalidAttributeError(attribute.key, attribute.value);
|
|
518
|
+
/** A `bytes1` as something readable: the character it is, plus the byte it was. */
|
|
519
|
+
function printable(byte) {
|
|
520
|
+
const code = Number.parseInt(byte.replace(/^0x/, ""), 16);
|
|
521
|
+
if (!Number.isFinite(code)) return `byte ${byte}`;
|
|
522
|
+
return code >= 33 && code <= 126 ? `"${String.fromCharCode(code)}" (${byte})` : `byte ${byte}`;
|
|
310
523
|
}
|
|
311
524
|
|
|
312
525
|
//#endregion
|
|
313
526
|
//#region src/utils/arkivTransactions.ts
|
|
314
527
|
const logger$6 = require_queryBuilder.getLogger("utils:arkiv-transactions");
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
}
|
|
319
|
-
const payload = [
|
|
320
|
-
(creates ?? []).map((item) => {
|
|
321
|
-
validateExpiresIn(item.expiresIn);
|
|
322
|
-
item.attributes.forEach(validateAttribute);
|
|
323
|
-
return [
|
|
324
|
-
(0, viem.toHex)(item.expiresIn / require_consts.BLOCK_TIME),
|
|
325
|
-
(0, viem.toHex)(item.contentType),
|
|
326
|
-
(0, viem.toHex)(item.payload),
|
|
327
|
-
item.attributes.filter((attribute) => typeof attribute.value === "string").map(formatAttributes),
|
|
328
|
-
item.attributes.filter((attribute) => typeof attribute.value === "number").map(formatAttributes)
|
|
329
|
-
];
|
|
330
|
-
}),
|
|
331
|
-
(updates ?? []).map((item) => {
|
|
332
|
-
validateExpiresIn(item.expiresIn);
|
|
333
|
-
item.attributes.forEach(validateAttribute);
|
|
334
|
-
return [
|
|
335
|
-
item.entityKey,
|
|
336
|
-
(0, viem.toHex)(item.contentType),
|
|
337
|
-
(0, viem.toHex)(item.expiresIn / require_consts.BLOCK_TIME),
|
|
338
|
-
(0, viem.toHex)(item.payload),
|
|
339
|
-
item.attributes.filter((attribute) => typeof attribute.value === "string").map(formatAttributes),
|
|
340
|
-
item.attributes.filter((attribute) => typeof attribute.value === "number").map(formatAttributes)
|
|
341
|
-
];
|
|
342
|
-
}),
|
|
343
|
-
(deletes ?? []).map((item) => item.entityKey),
|
|
344
|
-
(extensions ?? []).map((item) => {
|
|
345
|
-
validateExpiresIn(item.expiresIn);
|
|
346
|
-
return [item.entityKey, (0, viem.toHex)(item.expiresIn / require_consts.BLOCK_TIME)];
|
|
347
|
-
}),
|
|
348
|
-
(ownershipChanges ?? []).map((item) => [item.entityKey, item.newOwner])
|
|
349
|
-
];
|
|
350
|
-
logger$6("txData to send as RLP %o length %d", payload, payload.length);
|
|
351
|
-
return (0, viem.toRlp)(payload);
|
|
528
|
+
const MIME_REGEX = /^[a-z][a-z0-9!#$&\-^_]*\/[a-z0-9][a-z0-9!#$&\-^_.+]*$/;
|
|
529
|
+
function validateContentType(contentType) {
|
|
530
|
+
if (!MIME_REGEX.test(contentType)) throw new require_queryBuilder.InvalidContentTypeError(contentType);
|
|
352
531
|
}
|
|
353
|
-
|
|
532
|
+
const ENTITY_ERRORS_ABI = (0, viem.parseAbi)([
|
|
533
|
+
"error EmptyBatch()",
|
|
534
|
+
"error InvalidOpType(uint8 operation)",
|
|
535
|
+
"error NonCanonicalOperationData(uint8 operation)",
|
|
536
|
+
"error AttributesNotSorted()",
|
|
537
|
+
"error TooManyAttributes(uint256 count, uint256 maxCount)",
|
|
538
|
+
"error EmptyMutations(bytes32 entityKey)",
|
|
539
|
+
"error TombstoneInCreate(bytes32 name)",
|
|
540
|
+
"error TombstoneValueNotEmpty(bytes32 name)",
|
|
541
|
+
"error SystemAttributeNotWritable(bytes32 name)",
|
|
542
|
+
"error InvalidValueType(bytes32 name, uint8 typeId)",
|
|
543
|
+
"error Ident32Empty()",
|
|
544
|
+
"error Ident32InvalidByte(uint256 position, bytes1 value)",
|
|
545
|
+
"error EntityNotFound(bytes32 entityKey)",
|
|
546
|
+
"error EntityExpired(bytes32 entityKey, uint64 expiresAt)",
|
|
547
|
+
"error NotOwner(bytes32 entityKey, address caller, address owner)",
|
|
548
|
+
"error ReadOnlyEntity(bytes32 entityKey)",
|
|
549
|
+
"error ReservedCreationFlags(uint8 creationFlags)",
|
|
550
|
+
"error ExpiryDeadOnArrival(uint64 target, uint64 currentBlock)",
|
|
551
|
+
"error ExpiryNotExtended(bytes32 entityKey, uint64 newExpiresAt, uint64 currentExpiresAt)",
|
|
552
|
+
"error TransferToZeroAddress(bytes32 entityKey)",
|
|
553
|
+
"error TransferToSelf(bytes32 entityKey)"
|
|
554
|
+
]);
|
|
555
|
+
const EXECUTE_ABI$1 = [...EXECUTE_ABI, ...ENTITY_ERRORS_ABI];
|
|
556
|
+
async function sendArkivTransaction(client, ops, txParams) {
|
|
354
557
|
if (!client.account) throw new Error("Account required");
|
|
558
|
+
if (!client.chain) throw new Error("Chain required");
|
|
355
559
|
const walletClient = client;
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
560
|
+
const { creates, patches, deletes, extensions, ownershipChanges } = ops;
|
|
561
|
+
const expiryContext = { currentBlock: creates?.length || extensions?.length ? await walletClient.getBlockNumber() : 0n };
|
|
562
|
+
const createOps = (creates ?? []).map((item) => {
|
|
563
|
+
validateContentType(item.contentType);
|
|
564
|
+
return createOperation({
|
|
565
|
+
salt: item.salt === void 0 ? require_entity$1.randomSalt() : require_entity$1.validateSalt(item.salt),
|
|
566
|
+
expiry: require_expiry.resolveExpiry(item.expires, expiryContext),
|
|
567
|
+
creationFlags: require_flags.encodeCreationFlags(item.flags),
|
|
568
|
+
attributes: require_attr.encodeAttributes(item.attributes, {
|
|
569
|
+
payload: item.payload,
|
|
570
|
+
contentType: item.contentType
|
|
571
|
+
})
|
|
572
|
+
});
|
|
363
573
|
});
|
|
574
|
+
const patchOps = (patches ?? []).map((item) => {
|
|
575
|
+
if (item.contentType !== void 0) validateContentType(item.contentType);
|
|
576
|
+
const mutations = require_attr.encodeMutations(item);
|
|
577
|
+
if (mutations.length === 0) throw new require_queryBuilder.EmptyPatchError(item.entityKey);
|
|
578
|
+
return patchOperation({
|
|
579
|
+
entityKey: item.entityKey,
|
|
580
|
+
mutations
|
|
581
|
+
});
|
|
582
|
+
});
|
|
583
|
+
const extendOps = (extensions ?? []).map((item) => {
|
|
584
|
+
const expiry = require_expiry.resolveExpiry(item.expires, expiryContext);
|
|
585
|
+
return extendExpiryOperation({
|
|
586
|
+
entityKey: item.entityKey,
|
|
587
|
+
expiry
|
|
588
|
+
});
|
|
589
|
+
});
|
|
590
|
+
const operations = [
|
|
591
|
+
...createOps,
|
|
592
|
+
...patchOps,
|
|
593
|
+
...(deletes ?? []).map((item) => deleteOperation({ entityKey: item.entityKey })),
|
|
594
|
+
...extendOps,
|
|
595
|
+
...(ownershipChanges ?? []).map((item) => transferOwnershipOperation({
|
|
596
|
+
entityKey: item.entityKey,
|
|
597
|
+
newOwner: item.newOwner
|
|
598
|
+
}))
|
|
599
|
+
];
|
|
600
|
+
if (operations.length === 0) throw new Error("No operations to perform");
|
|
601
|
+
logger$6("Sending execute with %d operations %o", operations.length, operations);
|
|
364
602
|
try {
|
|
365
|
-
const
|
|
366
|
-
|
|
603
|
+
const txHash = await walletClient.writeContract({
|
|
604
|
+
address: require_expiry.ARKIV_ADDRESS,
|
|
605
|
+
abi: EXECUTE_ABI$1,
|
|
606
|
+
functionName: "execute",
|
|
607
|
+
args: [operations],
|
|
367
608
|
account: client.account,
|
|
368
609
|
chain: client.chain,
|
|
369
|
-
to: require_consts.ARKIV_ADDRESS,
|
|
370
|
-
value: 0n,
|
|
371
|
-
data: (0, viem.toHex)(compressed),
|
|
372
610
|
...txParams
|
|
373
611
|
});
|
|
374
612
|
const receipt = await walletClient.waitForTransactionReceipt({ hash: txHash });
|
|
375
613
|
logger$6("Tx receipt %o", receipt);
|
|
376
|
-
if (receipt.status === "reverted")
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
614
|
+
if (receipt.status === "reverted") {
|
|
615
|
+
try {
|
|
616
|
+
await walletClient.simulateContract({
|
|
617
|
+
address: require_expiry.ARKIV_ADDRESS,
|
|
618
|
+
abi: EXECUTE_ABI$1,
|
|
619
|
+
functionName: "execute",
|
|
620
|
+
args: [operations],
|
|
621
|
+
account: client.account,
|
|
622
|
+
chain: client.chain
|
|
623
|
+
});
|
|
624
|
+
} catch (err) {
|
|
625
|
+
const error = err;
|
|
626
|
+
const reason = describeEntityRevert(err) ?? error.shortMessage ?? error.cause?.details ?? "No reason provided by backend.";
|
|
627
|
+
throw new require_queryBuilder.EntityMutationError(`Transaction ${receipt.transactionHash} reverted. Reason: ${reason}`);
|
|
628
|
+
}
|
|
629
|
+
throw new require_queryBuilder.EntityMutationError(`Transaction ${receipt.transactionHash} reverted. No reason provided by backend.`);
|
|
390
630
|
}
|
|
391
|
-
return
|
|
631
|
+
return {
|
|
632
|
+
receipt,
|
|
633
|
+
...readAppliedOperations(receipt, {
|
|
634
|
+
creates: createOps.length,
|
|
635
|
+
extensions: extendOps.length
|
|
636
|
+
})
|
|
637
|
+
};
|
|
392
638
|
} catch (error) {
|
|
639
|
+
const described = error instanceof require_queryBuilder.EntityMutationError ? void 0 : describeEntityRevert(error);
|
|
640
|
+
if (described !== void 0) throw new require_queryBuilder.EntityMutationError(`Transaction failed: ${described}`, { cause: error });
|
|
393
641
|
let message = "Transaction failed";
|
|
394
642
|
if (error instanceof viem.TransactionExecutionError) message += `: ${error.details}`;
|
|
395
|
-
else if (error instanceof
|
|
396
|
-
|
|
397
|
-
|
|
643
|
+
else if (error instanceof viem.ContractFunctionExecutionError) {
|
|
644
|
+
logger$6("Contract function execution error data:", error.shortMessage);
|
|
645
|
+
if (error.cause instanceof viem.ContractFunctionRevertedError) message += `: ${error.cause.message}`;
|
|
646
|
+
else message += ": Execution error without revert data";
|
|
647
|
+
} else if (error instanceof require_queryBuilder.EntityMutationError) throw error;
|
|
648
|
+
else if (error instanceof Error) message += `: ${error.message}`;
|
|
649
|
+
throw new require_queryBuilder.EntityMutationError(message, { cause: error });
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* The keys and expiries the engine recorded, read back from the events the batch emitted.
|
|
654
|
+
*/
|
|
655
|
+
function readAppliedOperations(receipt, expected) {
|
|
656
|
+
const createdEntityKeys = [];
|
|
657
|
+
const createdExpiries = [];
|
|
658
|
+
const extendedExpiries = [];
|
|
659
|
+
for (const log of receipt.logs ?? []) {
|
|
660
|
+
if (log.address.toLowerCase() !== require_expiry.ARKIV_ADDRESS.toLowerCase()) continue;
|
|
661
|
+
const decoded = decodeEntityLog(log);
|
|
662
|
+
if (decoded === void 0) continue;
|
|
663
|
+
if (decoded.eventName === "EntityCreated") {
|
|
664
|
+
createdEntityKeys.push(decoded.args.entityKey);
|
|
665
|
+
createdExpiries.push(decoded.args.expiresAt);
|
|
666
|
+
} else if (decoded.eventName === "ExpiryExtended") extendedExpiries.push(decoded.args.expiresAt);
|
|
667
|
+
}
|
|
668
|
+
assertCount(receipt, "create", createdEntityKeys.length, expected.creates);
|
|
669
|
+
assertCount(receipt, "extension", extendedExpiries.length, expected.extensions);
|
|
670
|
+
return {
|
|
671
|
+
createdEntityKeys,
|
|
672
|
+
createdExpiries,
|
|
673
|
+
extendedExpiries
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
/** One log as an entity event, or `undefined` for anything this SDK has no name for. */
|
|
677
|
+
function decodeEntityLog(log) {
|
|
678
|
+
try {
|
|
679
|
+
return (0, viem.decodeEventLog)({
|
|
680
|
+
abi: require_entity$1.ENTITY_EVENTS_ABI,
|
|
681
|
+
topics: log.topics,
|
|
682
|
+
data: log.data
|
|
683
|
+
});
|
|
684
|
+
} catch {
|
|
685
|
+
return;
|
|
398
686
|
}
|
|
399
687
|
}
|
|
688
|
+
function assertCount(receipt, what, got, want) {
|
|
689
|
+
if (got === want) return;
|
|
690
|
+
throw new require_queryBuilder.EntityMutationError(`Transaction ${receipt.transactionHash} succeeded — do not retry it — but emitted ${got} ${what} event(s) for ${want} ${what} operation(s). The batch was applied; the SDK cannot say which entity each operation produced, so read them back to find them.`);
|
|
691
|
+
}
|
|
400
692
|
|
|
401
693
|
//#endregion
|
|
402
694
|
//#region src/actions/wallet/changeOwnership.ts
|
|
403
695
|
const logger$5 = require_queryBuilder.getLogger("actions:wallet:change-ownership");
|
|
404
696
|
async function changeOwnership(client, data, txParams) {
|
|
405
697
|
logger$5("changeOwnership %o", data);
|
|
406
|
-
const receipt = await sendArkivTransaction(client,
|
|
698
|
+
const { receipt } = await sendArkivTransaction(client, { ownershipChanges: [data] }, txParams);
|
|
407
699
|
logger$5("Receipt from changeOwnership %o", receipt);
|
|
408
700
|
return {
|
|
409
701
|
txHash: receipt.transactionHash,
|
|
@@ -416,11 +708,15 @@ async function changeOwnership(client, data, txParams) {
|
|
|
416
708
|
const logger$4 = require_queryBuilder.getLogger("actions:wallet:create-entity");
|
|
417
709
|
async function createEntity(client, data, txParams) {
|
|
418
710
|
logger$4("createEntity %o", data);
|
|
419
|
-
const receipt = await sendArkivTransaction(client,
|
|
711
|
+
const { receipt, createdEntityKeys, createdExpiries } = await sendArkivTransaction(client, { creates: [data] }, txParams);
|
|
420
712
|
logger$4("Receipt from createEntity %o", receipt);
|
|
713
|
+
const [entityKey] = createdEntityKeys;
|
|
714
|
+
const [expiresAt] = createdExpiries;
|
|
715
|
+
if (entityKey === void 0 || expiresAt === void 0) throw new require_queryBuilder.EntityMutationError(`Transaction ${receipt.transactionHash} succeeded, but the receipt did not carry the expected entity key or expiry.`);
|
|
421
716
|
return {
|
|
422
717
|
txHash: receipt.transactionHash,
|
|
423
|
-
entityKey
|
|
718
|
+
entityKey,
|
|
719
|
+
expiresAt
|
|
424
720
|
};
|
|
425
721
|
}
|
|
426
722
|
|
|
@@ -429,7 +725,7 @@ async function createEntity(client, data, txParams) {
|
|
|
429
725
|
const logger$3 = require_queryBuilder.getLogger("actions:wallet:delete-entity");
|
|
430
726
|
async function deleteEntity(client, data, txParams) {
|
|
431
727
|
logger$3("deleteEntity %o", data);
|
|
432
|
-
const receipt = await sendArkivTransaction(client,
|
|
728
|
+
const { receipt } = await sendArkivTransaction(client, { deletes: [data] }, txParams);
|
|
433
729
|
logger$3("Receipt from deleteEntity %o", receipt);
|
|
434
730
|
return {
|
|
435
731
|
txHash: receipt.transactionHash,
|
|
@@ -442,74 +738,43 @@ async function deleteEntity(client, data, txParams) {
|
|
|
442
738
|
const logger$2 = require_queryBuilder.getLogger("actions:wallet:extend-entity");
|
|
443
739
|
async function extendEntity(client, data, txParams) {
|
|
444
740
|
logger$2("extendEntity %o", data);
|
|
445
|
-
const receipt = await sendArkivTransaction(client,
|
|
741
|
+
const { receipt, extendedExpiries } = await sendArkivTransaction(client, { extensions: [data] }, txParams);
|
|
446
742
|
logger$2("Receipt from extendEntity %o", receipt);
|
|
743
|
+
const [expiresAt] = extendedExpiries;
|
|
744
|
+
if (expiresAt === void 0) throw new require_queryBuilder.EntityMutationError(`Transaction ${receipt.transactionHash} succeeded, but the receipt did not carry the expected entity expiry.`);
|
|
447
745
|
return {
|
|
448
746
|
txHash: receipt.transactionHash,
|
|
449
|
-
entityKey:
|
|
747
|
+
entityKey: data.entityKey,
|
|
748
|
+
expiresAt
|
|
450
749
|
};
|
|
451
750
|
}
|
|
452
751
|
|
|
453
752
|
//#endregion
|
|
454
753
|
//#region src/actions/wallet/mutateEntities.ts
|
|
455
754
|
const logger$1 = require_queryBuilder.getLogger("actions:wallet:mutate-entities");
|
|
456
|
-
function parseReceipt(receipt, params) {
|
|
457
|
-
const createdEntities = [];
|
|
458
|
-
const updatedEntities = [];
|
|
459
|
-
const deletedEntities = [];
|
|
460
|
-
const extendedEntities = [];
|
|
461
|
-
const ownershipChanges = [];
|
|
462
|
-
const totalCreates = params.creates?.length ?? 0;
|
|
463
|
-
const totalUpdates = params.updates?.length ?? 0;
|
|
464
|
-
const totalDeletes = params.deletes?.length ?? 0;
|
|
465
|
-
const totalExtensions = params.extensions?.length ?? 0;
|
|
466
|
-
for (let index = 0; index < receipt.logs.length; index++) {
|
|
467
|
-
const log = receipt.logs[index];
|
|
468
|
-
if (index < totalCreates) createdEntities.push(log.topics[1]);
|
|
469
|
-
else if (index < totalCreates + totalDeletes) deletedEntities.push(log.topics[1]);
|
|
470
|
-
else if (index < totalCreates + totalUpdates + totalDeletes) updatedEntities.push(log.topics[1]);
|
|
471
|
-
else if (index < totalCreates + totalUpdates + totalDeletes + totalExtensions) extendedEntities.push(log.topics[1]);
|
|
472
|
-
else ownershipChanges.push(log.topics[1]);
|
|
473
|
-
}
|
|
474
|
-
return {
|
|
475
|
-
createdEntities,
|
|
476
|
-
updatedEntities,
|
|
477
|
-
deletedEntities,
|
|
478
|
-
extendedEntities,
|
|
479
|
-
ownershipChanges
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
755
|
async function mutateEntities(client, data, txParams) {
|
|
483
|
-
|
|
484
|
-
const receipt = await sendArkivTransaction(client, opsToTxData({
|
|
485
|
-
creates: data.creates ?? [],
|
|
486
|
-
updates: data.updates ?? [],
|
|
487
|
-
deletes: data.deletes ?? [],
|
|
488
|
-
extensions: data.extensions ?? [],
|
|
489
|
-
ownershipChanges: data.ownershipChanges ?? []
|
|
490
|
-
}), txParams);
|
|
756
|
+
const { receipt, createdEntityKeys } = await sendArkivTransaction(client, data, txParams);
|
|
491
757
|
logger$1("Receipt from mutateEntities %o", receipt);
|
|
492
|
-
const { createdEntities, updatedEntities, deletedEntities, extendedEntities, ownershipChanges } = parseReceipt(receipt, data);
|
|
493
758
|
return {
|
|
494
759
|
txHash: receipt.transactionHash,
|
|
495
|
-
createdEntities,
|
|
496
|
-
|
|
497
|
-
deletedEntities,
|
|
498
|
-
extendedEntities,
|
|
499
|
-
ownershipChanges
|
|
760
|
+
createdEntities: createdEntityKeys,
|
|
761
|
+
patchedEntities: (data.patches ?? []).map((p) => p.entityKey),
|
|
762
|
+
deletedEntities: (data.deletes ?? []).map((d) => d.entityKey),
|
|
763
|
+
extendedEntities: (data.extensions ?? []).map((e) => e.entityKey),
|
|
764
|
+
ownershipChanges: (data.ownershipChanges ?? []).map((o) => o.entityKey)
|
|
500
765
|
};
|
|
501
766
|
}
|
|
502
767
|
|
|
503
768
|
//#endregion
|
|
504
|
-
//#region src/actions/wallet/
|
|
505
|
-
const logger = require_queryBuilder.getLogger("actions:wallet:
|
|
506
|
-
async function
|
|
507
|
-
logger("
|
|
508
|
-
const receipt = await sendArkivTransaction(client,
|
|
509
|
-
logger("Receipt from
|
|
769
|
+
//#region src/actions/wallet/patchEntity.ts
|
|
770
|
+
const logger = require_queryBuilder.getLogger("actions:wallet:patch-entity");
|
|
771
|
+
async function patchEntity(client, data, txParams) {
|
|
772
|
+
logger("patchEntity %o", data);
|
|
773
|
+
const { receipt } = await sendArkivTransaction(client, { patches: [data] }, txParams);
|
|
774
|
+
logger("Receipt from patchEntity %o", receipt);
|
|
510
775
|
return {
|
|
511
776
|
txHash: receipt.transactionHash,
|
|
512
|
-
entityKey:
|
|
777
|
+
entityKey: data.entityKey
|
|
513
778
|
};
|
|
514
779
|
}
|
|
515
780
|
|
|
@@ -518,7 +783,7 @@ async function updateEntity(client, data, txParams) {
|
|
|
518
783
|
function walletArkivActions(client) {
|
|
519
784
|
return {
|
|
520
785
|
createEntity: (data, txParams) => createEntity(client, data, txParams),
|
|
521
|
-
|
|
786
|
+
patchEntity: (data, txParams) => patchEntity(client, data, txParams),
|
|
522
787
|
deleteEntity: (data, txParams) => deleteEntity(client, data, txParams),
|
|
523
788
|
extendEntity: (data, txParams) => extendEntity(client, data, txParams),
|
|
524
789
|
changeOwnership: (data, txParams) => changeOwnership(client, data, txParams),
|
|
@@ -529,36 +794,42 @@ function walletArkivActions(client) {
|
|
|
529
794
|
//#endregion
|
|
530
795
|
//#region src/clients/createWalletClient.ts
|
|
531
796
|
/**
|
|
532
|
-
* Creates a
|
|
797
|
+
* Creates a Wallet Client with a given [Transport](https://viem.sh/docs/clients/intro) configured
|
|
798
|
+
* for a [Chain](https://viem.sh/docs/clients/chains) and an account.
|
|
533
799
|
*
|
|
534
|
-
* - Docs: https://docs.arkiv.network/ts-sdk/clients/
|
|
800
|
+
* - Docs: https://docs.arkiv.network/ts-sdk/clients/wallet
|
|
535
801
|
*
|
|
536
|
-
* A
|
|
802
|
+
* A Wallet Client signs and sends transactions, so it carries an `account` and exposes everything
|
|
803
|
+
* that mutates state — `createEntity`, `patchEntity`, `deleteEntity`, `extendEntity`,
|
|
804
|
+
* `changeOwnership` and `mutateEntities` — on top of the read actions a Public Client has.
|
|
537
805
|
*
|
|
538
806
|
* @param parameters - Configuration object for the wallet client (chain, transport, account, etc.)
|
|
539
807
|
* @returns A Arkiv Wallet Client. {@link WalletArkivClient}
|
|
540
808
|
*
|
|
541
809
|
* @example
|
|
542
|
-
* import {
|
|
543
|
-
* import {
|
|
810
|
+
* import { createWalletClient } from "@arkiv-network/sdk"
|
|
811
|
+
* import { cheesecake } from "@arkiv-network/sdk/chains"
|
|
812
|
+
* import { http } from "viem"
|
|
813
|
+
* import { privateKeyToAccount } from "viem/accounts"
|
|
544
814
|
*
|
|
545
|
-
* const client =
|
|
546
|
-
* chain:
|
|
815
|
+
* const client = createWalletClient({
|
|
816
|
+
* chain: cheesecake,
|
|
547
817
|
* transport: http(),
|
|
818
|
+
* account: privateKeyToAccount("0x..."),
|
|
548
819
|
* })
|
|
549
820
|
*/
|
|
550
821
|
function createWalletClient(parameters) {
|
|
551
|
-
const { key = "wallet", name = "Wallet Client" } = parameters;
|
|
822
|
+
const { key: key$1 = "wallet", name = "Wallet Client" } = parameters;
|
|
552
823
|
return (0, viem.createClient)({
|
|
553
824
|
...parameters,
|
|
554
|
-
key,
|
|
825
|
+
key: key$1,
|
|
555
826
|
name
|
|
556
827
|
}).extend(viem.publicActions).extend(viem.walletActions).extend(walletArkivActions);
|
|
557
828
|
}
|
|
558
829
|
|
|
559
830
|
//#endregion
|
|
560
831
|
//#region src/utils/chains.ts
|
|
561
|
-
const chainMap = new Map(Object.entries(require_chains.chains_exports).map(([key, value]) => [key.toLowerCase(), value]));
|
|
832
|
+
const chainMap = new Map(Object.entries(require_chains.chains_exports).map(([key$1, value]) => [key$1.toLowerCase(), value]));
|
|
562
833
|
/**
|
|
563
834
|
* Get a chain from its name
|
|
564
835
|
* @param name - The name of the chain, case insensitive
|
|
@@ -572,14 +843,61 @@ function chainFromName(name) {
|
|
|
572
843
|
}
|
|
573
844
|
|
|
574
845
|
//#endregion
|
|
846
|
+
exports.ConflictingMutationError = require_attr.ConflictingMutationError;
|
|
847
|
+
exports.DECIMAL_SCALE = require_attr.DECIMAL_SCALE;
|
|
848
|
+
exports.DECIMAL_UNIT = require_attr.DECIMAL_UNIT;
|
|
849
|
+
exports.ENTITY_EVENTS_ABI = require_entity$1.ENTITY_EVENTS_ABI;
|
|
850
|
+
exports.EmptyPatchError = require_queryBuilder.EmptyPatchError;
|
|
851
|
+
exports.Entity = require_entity.Entity;
|
|
575
852
|
exports.EntityMutationError = require_queryBuilder.EntityMutationError;
|
|
576
|
-
exports.
|
|
577
|
-
exports.
|
|
578
|
-
exports.
|
|
853
|
+
exports.ExpirationTime = require_payload.ExpirationTime;
|
|
854
|
+
exports.I32_MAX = require_attr.I32_MAX;
|
|
855
|
+
exports.I32_MIN = require_attr.I32_MIN;
|
|
856
|
+
exports.InvalidAttributeNameError = require_attr.InvalidAttributeNameError;
|
|
857
|
+
exports.InvalidContentTypeError = require_queryBuilder.InvalidContentTypeError;
|
|
858
|
+
exports.InvalidCreationFlagsError = require_errors.InvalidCreationFlagsError;
|
|
859
|
+
exports.InvalidExpiryError = require_errors.InvalidExpiryError;
|
|
860
|
+
exports.InvalidSaltError = require_errors.InvalidSaltError;
|
|
861
|
+
exports.InvalidValueError = require_attr.InvalidValueError;
|
|
862
|
+
exports.MAX_ATTRIBUTES = require_attr.MAX_ATTRIBUTES;
|
|
863
|
+
exports.MAX_EXPIRES_AT = require_expiry.MAX_EXPIRES_AT;
|
|
864
|
+
exports.MAX_NAME_BYTES = require_attr.MAX_NAME_BYTES;
|
|
865
|
+
exports.MAX_PAYLOAD_BYTES = require_attr.MAX_PAYLOAD_BYTES;
|
|
866
|
+
exports.MAX_SALT = require_entity$1.MAX_SALT;
|
|
867
|
+
exports.MAX_STRING_BYTES = require_attr.MAX_STRING_BYTES;
|
|
868
|
+
exports.MissingValueError = require_attr.MissingValueError;
|
|
579
869
|
exports.NoEntityFoundError = require_queryBuilder.NoEntityFoundError;
|
|
580
870
|
exports.NoMoreResultsError = require_queryBuilder.NoMoreResultsError;
|
|
871
|
+
exports.NoRandomSourceError = require_errors.NoRandomSourceError;
|
|
872
|
+
exports.OperationType = require_expiry.OperationType;
|
|
873
|
+
exports.TooManyAttributesError = require_attr.TooManyAttributesError;
|
|
874
|
+
exports.U256_MAX = require_attr.U256_MAX;
|
|
875
|
+
exports.U64_MAX = require_attr.U64_MAX;
|
|
876
|
+
exports.UnknownAttributeTypeError = require_attr.UnknownAttributeTypeError;
|
|
877
|
+
exports.UntypedValueError = require_attr.UntypedValueError;
|
|
878
|
+
exports.addr = require_attr.addr;
|
|
879
|
+
exports.bool = require_attr.bool;
|
|
880
|
+
exports.bytes32 = require_attr.bytes32;
|
|
581
881
|
exports.chainFromName = chainFromName;
|
|
582
882
|
exports.createPublicClient = createPublicClient;
|
|
583
883
|
exports.createWalletClient = createWalletClient;
|
|
884
|
+
exports.dec = require_attr.dec;
|
|
885
|
+
exports.decFromUnits = require_attr.decFromUnits;
|
|
886
|
+
exports.decUnits = require_attr.decUnits;
|
|
887
|
+
exports.decodeCreationFlags = require_flags.decodeCreationFlags;
|
|
888
|
+
exports.encodeCreationFlags = require_flags.encodeCreationFlags;
|
|
889
|
+
exports.i32 = require_attr.i32;
|
|
890
|
+
exports.isArkivValue = require_attr.isArkivValue;
|
|
891
|
+
exports.isValidAttributeName = require_attr.isValidAttributeName;
|
|
584
892
|
exports.jsonToPayload = require_payload.jsonToPayload;
|
|
585
|
-
exports.
|
|
893
|
+
exports.key = require_attr.key;
|
|
894
|
+
exports.predictEntityKey = require_entity$1.predictEntityKey;
|
|
895
|
+
exports.randomSalt = require_entity$1.randomSalt;
|
|
896
|
+
exports.resolveExpiry = require_expiry.resolveExpiry;
|
|
897
|
+
exports.str = require_attr.str;
|
|
898
|
+
exports.stringToPayload = require_payload.stringToPayload;
|
|
899
|
+
exports.toBlocks = require_expiry.toBlocks;
|
|
900
|
+
exports.toValue = require_attr.toValue;
|
|
901
|
+
exports.u256 = require_attr.u256;
|
|
902
|
+
exports.u64 = require_attr.u64;
|
|
903
|
+
exports.validateAttributeName = require_attr.validateAttributeName;
|