@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/dist/index.cjs
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
const require_chains = require('./chains-
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
require('./
|
|
6
|
-
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');
|
|
7
11
|
let viem = require("viem");
|
|
12
|
+
let viem_actions = require("viem/actions");
|
|
8
13
|
|
|
9
14
|
//#region src/actions/public/getBlockTiming.ts
|
|
10
|
-
const logger$
|
|
15
|
+
const logger$9 = require_queryBuilder.getLogger("actions:public:get-block-timing");
|
|
11
16
|
async function getBlockTiming(client) {
|
|
12
17
|
const blockTiming = await client.request({
|
|
13
18
|
method: "arkiv_getBlockTiming",
|
|
14
19
|
params: []
|
|
15
20
|
});
|
|
16
|
-
logger$
|
|
21
|
+
logger$9("Block timing %o", blockTiming);
|
|
17
22
|
return {
|
|
18
23
|
currentBlock: BigInt(blockTiming.current_block),
|
|
19
24
|
currentBlockTime: blockTiming.current_block_time,
|
|
@@ -23,33 +28,26 @@ async function getBlockTiming(client) {
|
|
|
23
28
|
|
|
24
29
|
//#endregion
|
|
25
30
|
//#region src/actions/public/getEntity.ts
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
expiration: true,
|
|
43
|
-
owner: true,
|
|
44
|
-
creator: true,
|
|
45
|
-
createdAtBlock: true,
|
|
46
|
-
lastModifiedAtBlock: true,
|
|
47
|
-
transactionIndexInBlock: true,
|
|
48
|
-
operationIndexInTransaction: true
|
|
49
|
-
} }]
|
|
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
|
|
50
47
|
});
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
const entity = entities[0];
|
|
49
|
+
if (entity === void 0) throw new require_queryBuilder.NoEntityFoundError(entityKey);
|
|
50
|
+
return entity;
|
|
53
51
|
}
|
|
54
52
|
|
|
55
53
|
//#endregion
|
|
@@ -61,220 +59,550 @@ async function getEntityCount(client) {
|
|
|
61
59
|
});
|
|
62
60
|
}
|
|
63
61
|
|
|
62
|
+
//#endregion
|
|
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
|
+
}])
|
|
105
|
+
};
|
|
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 }) {
|
|
140
|
+
return {
|
|
141
|
+
operation: require_expiry.OperationType.Delete,
|
|
142
|
+
operationData: (0, viem.encodeAbiParameters)(PAYLOAD_PARAMS[require_expiry.OperationType.Delete], [{ entityKey }])
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
//#endregion
|
|
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
|
+
|
|
64
233
|
//#endregion
|
|
65
234
|
//#region src/actions/public/query.ts
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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 },
|
|
334
|
+
onLogs: (logs) => {
|
|
335
|
+
logger$7("logs %o", logs);
|
|
336
|
+
for (const log of logs) {
|
|
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;
|
|
349
|
+
}
|
|
350
|
+
emit(event);
|
|
351
|
+
}
|
|
80
352
|
},
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
353
|
+
onError: (error) => reportError(error)
|
|
354
|
+
});
|
|
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
|
|
93
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
|
+
}
|
|
404
|
+
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region src/clients/decorators/arkivPublic.ts
|
|
407
|
+
function publicArkivActions(client) {
|
|
94
408
|
return {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
409
|
+
getEntity: (key$1) => getEntity(client, key$1),
|
|
410
|
+
query: (rawQuery, queryOptions) => query(client, rawQuery, queryOptions),
|
|
411
|
+
select: (selection) => new require_queryBuilder.SelectQueryBuilder(client, selection),
|
|
412
|
+
getBlockTiming: () => getBlockTiming(client),
|
|
413
|
+
getEntityCount: () => getEntityCount(client),
|
|
414
|
+
getEntityNonce: (owner) => getEntityNonce(client, owner),
|
|
415
|
+
predictEntityKeys: (parameters) => predictEntityKeys(client, parameters),
|
|
416
|
+
watchEntityEvents: (parameters) => watchEntityEvents(client, parameters)
|
|
98
417
|
};
|
|
99
418
|
}
|
|
100
419
|
|
|
420
|
+
//#endregion
|
|
421
|
+
//#region src/clients/createPublicClient.ts
|
|
422
|
+
/**
|
|
423
|
+
* Creates a Public Client with a given [Transport](https://viem.sh/docs/clients/intro) configured for a [Chain](https://viem.sh/docs/clients/chains).
|
|
424
|
+
*
|
|
425
|
+
* - Docs: https://docs.arkiv.network/ts-sdk/clients/public
|
|
426
|
+
*
|
|
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).
|
|
428
|
+
*
|
|
429
|
+
* @param parameters - Configuration object for the public client (chain, transport, etc.)
|
|
430
|
+
* @returns A Arkiv Public Client. {@link PublicArkivClient}
|
|
431
|
+
*
|
|
432
|
+
* @example
|
|
433
|
+
* import { createPublicClient } from "@arkiv-network/sdk"
|
|
434
|
+
* import { cheesecake } from "@arkiv-network/sdk/chains"
|
|
435
|
+
* import { http } from "viem"
|
|
436
|
+
*
|
|
437
|
+
* const client = createPublicClient({
|
|
438
|
+
* chain: cheesecake,
|
|
439
|
+
* transport: http(),
|
|
440
|
+
* })
|
|
441
|
+
*/
|
|
442
|
+
function createPublicClient(parameters) {
|
|
443
|
+
const { key: key$1 = "public", name = "Public Client" } = parameters;
|
|
444
|
+
return (0, viem.createClient)({
|
|
445
|
+
...parameters,
|
|
446
|
+
key: key$1,
|
|
447
|
+
name
|
|
448
|
+
}).extend(viem.publicActions).extend(publicArkivActions);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
//#endregion
|
|
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}`;
|
|
472
|
+
}
|
|
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})`;
|
|
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;
|
|
502
|
+
}
|
|
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;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
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;
|
|
517
|
+
}
|
|
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}`;
|
|
523
|
+
}
|
|
524
|
+
|
|
101
525
|
//#endregion
|
|
102
526
|
//#region src/utils/arkivTransactions.ts
|
|
103
|
-
const logger$
|
|
527
|
+
const logger$6 = require_queryBuilder.getLogger("utils:arkiv-transactions");
|
|
104
528
|
const MIME_REGEX = /^[a-z][a-z0-9!#$&\-^_]*\/[a-z0-9][a-z0-9!#$&\-^_.+]*$/;
|
|
105
529
|
function validateContentType(contentType) {
|
|
106
530
|
if (!MIME_REGEX.test(contentType)) throw new require_queryBuilder.InvalidContentTypeError(contentType);
|
|
107
531
|
}
|
|
108
|
-
const ENTITY_EXECUTE_ABI = (0, viem.parseAbi)(["function execute((uint8 operationType, bytes32 entityKey, bytes payload, (bytes32[4] data) contentType, (bytes32 name, uint8 valueType, bytes32[4] value)[] attributes, uint32 expiresIn, address newOwner)[] ops) external"]);
|
|
109
|
-
const ENTITY_OPERATION_EVENT_ABI = (0, viem.parseAbi)(["event EntityOperation(bytes32 indexed entityKey, uint8 indexed operationType, address indexed owner, uint32 expiresAt, bytes32 entityHash)"]);
|
|
110
532
|
const ENTITY_ERRORS_ABI = (0, viem.parseAbi)([
|
|
111
533
|
"error EmptyBatch()",
|
|
534
|
+
"error InvalidOpType(uint8 operation)",
|
|
535
|
+
"error NonCanonicalOperationData(uint8 operation)",
|
|
112
536
|
"error AttributesNotSorted()",
|
|
113
|
-
"error InvalidValueType(bytes32 name, uint8 valueType)",
|
|
114
|
-
"error InvalidOpType(uint8 operationType)",
|
|
115
|
-
"error ExpiryInPast(uint32 expiresAt, uint32 currentBlock)",
|
|
116
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)",
|
|
117
545
|
"error EntityNotFound(bytes32 entityKey)",
|
|
546
|
+
"error EntityExpired(bytes32 entityKey, uint64 expiresAt)",
|
|
118
547
|
"error NotOwner(bytes32 entityKey, address caller, address owner)",
|
|
119
|
-
"error
|
|
120
|
-
"error
|
|
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)",
|
|
121
552
|
"error TransferToZeroAddress(bytes32 entityKey)",
|
|
122
|
-
"error TransferToSelf(bytes32 entityKey)"
|
|
123
|
-
"error EntityNotExpired(bytes32 entityKey, uint32 expiresAt)",
|
|
124
|
-
"error Ident32Empty()",
|
|
125
|
-
"error Ident32TooLong(uint256 length)",
|
|
126
|
-
"error Ident32InvalidByte(uint256 position, bytes1 value)",
|
|
127
|
-
"error MimeEmpty()",
|
|
128
|
-
"error MimeTooLong(uint256 length, uint256 maxLength)",
|
|
129
|
-
"error MimeInvalidByte(uint256 position, bytes1 value)",
|
|
130
|
-
"error MimeIncomplete()"
|
|
553
|
+
"error TransferToSelf(bytes32 entityKey)"
|
|
131
554
|
]);
|
|
132
|
-
const EXECUTE_ABI = [...
|
|
133
|
-
const ENTITY_NONCE_ABI = (0, viem.parseAbi)(["function nonces(address owner) view returns (uint32)"]);
|
|
134
|
-
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
135
|
-
const ZERO_32 = `0x${"00".repeat(32)}`;
|
|
136
|
-
const EMPTY_BYTES128 = [
|
|
137
|
-
ZERO_32,
|
|
138
|
-
ZERO_32,
|
|
139
|
-
ZERO_32,
|
|
140
|
-
ZERO_32
|
|
141
|
-
];
|
|
142
|
-
function encodeBytes128(data) {
|
|
143
|
-
const padded = new Uint8Array(128);
|
|
144
|
-
padded.set(data.slice(0, 128));
|
|
145
|
-
return [
|
|
146
|
-
(0, viem.toHex)(padded.slice(0, 32)),
|
|
147
|
-
(0, viem.toHex)(padded.slice(32, 64)),
|
|
148
|
-
(0, viem.toHex)(padded.slice(64, 96)),
|
|
149
|
-
(0, viem.toHex)(padded.slice(96, 128))
|
|
150
|
-
];
|
|
151
|
-
}
|
|
152
|
-
function encodeMime128(contentType) {
|
|
153
|
-
return { data: contentType ? encodeBytes128((0, viem.stringToBytes)(contentType)) : EMPTY_BYTES128 };
|
|
154
|
-
}
|
|
155
|
-
function encodeAttribute(attr) {
|
|
156
|
-
require_queryBuilder.validateAttribute(attr);
|
|
157
|
-
const name = (0, viem.toHex)(attr.key, { size: 32 });
|
|
158
|
-
if (typeof attr.value === "string") {
|
|
159
|
-
if (require_queryBuilder.isEntityKey(attr.value)) return {
|
|
160
|
-
name,
|
|
161
|
-
valueType: require_queryBuilder.RpcAttributeValueType.EntityKey,
|
|
162
|
-
value: [
|
|
163
|
-
(0, viem.toHex)((0, viem.toBytes)(attr.value), { size: 32 }),
|
|
164
|
-
ZERO_32,
|
|
165
|
-
ZERO_32,
|
|
166
|
-
ZERO_32
|
|
167
|
-
]
|
|
168
|
-
};
|
|
169
|
-
return {
|
|
170
|
-
name,
|
|
171
|
-
valueType: require_queryBuilder.RpcAttributeValueType.String,
|
|
172
|
-
value: encodeBytes128((0, viem.stringToBytes)(attr.value))
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
return {
|
|
176
|
-
name,
|
|
177
|
-
valueType: require_queryBuilder.RpcAttributeValueType.Uint,
|
|
178
|
-
value: [
|
|
179
|
-
(0, viem.toHex)(BigInt(attr.value), { size: 32 }),
|
|
180
|
-
ZERO_32,
|
|
181
|
-
ZERO_32,
|
|
182
|
-
ZERO_32
|
|
183
|
-
]
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
function encodeAttributes(attrs) {
|
|
187
|
-
const encoded = attrs.map((attr) => ({
|
|
188
|
-
key: attr.key,
|
|
189
|
-
...encodeAttribute(attr)
|
|
190
|
-
})).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
191
|
-
for (let i = 1; i < encoded.length; i++) if (encoded[i].name === encoded[i - 1].name) throw new require_queryBuilder.DuplicateAttributeError(encoded[i].key);
|
|
192
|
-
return encoded.map(({ key: _,...attr }) => attr);
|
|
193
|
-
}
|
|
194
|
-
function toBTL(expiresIn) {
|
|
195
|
-
require_queryBuilder.validateExpiresIn(expiresIn);
|
|
196
|
-
return Math.ceil(expiresIn / require_consts.BLOCK_TIME);
|
|
197
|
-
}
|
|
198
|
-
function deriveEntityKey(chainId, owner, nonce) {
|
|
199
|
-
return (0, viem.keccak256)((0, viem.encodePacked)([
|
|
200
|
-
"uint256",
|
|
201
|
-
"address",
|
|
202
|
-
"address",
|
|
203
|
-
"uint32"
|
|
204
|
-
], [
|
|
205
|
-
BigInt(chainId),
|
|
206
|
-
require_consts.ARKIV_ADDRESS,
|
|
207
|
-
owner,
|
|
208
|
-
Number(nonce)
|
|
209
|
-
]));
|
|
210
|
-
}
|
|
555
|
+
const EXECUTE_ABI$1 = [...EXECUTE_ABI, ...ENTITY_ERRORS_ABI];
|
|
211
556
|
async function sendArkivTransaction(client, ops, txParams) {
|
|
212
557
|
if (!client.account) throw new Error("Account required");
|
|
213
558
|
if (!client.chain) throw new Error("Chain required");
|
|
214
559
|
const walletClient = client;
|
|
215
|
-
const { creates,
|
|
216
|
-
const
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
newOwner: ZERO_ADDRESS
|
|
235
|
-
})),
|
|
236
|
-
...(updates ?? []).map((item) => ({
|
|
237
|
-
operationType: require_entity.EntityOperationType.Update,
|
|
238
|
-
entityKey: item.entityKey,
|
|
239
|
-
payload: (0, viem.toHex)(item.payload),
|
|
240
|
-
contentType: encodeMime128(item.contentType),
|
|
241
|
-
attributes: encodeAttributes(item.attributes),
|
|
242
|
-
expiresIn: 0,
|
|
243
|
-
newOwner: ZERO_ADDRESS
|
|
244
|
-
})),
|
|
245
|
-
...(deletes ?? []).map((item) => ({
|
|
246
|
-
operationType: require_entity.EntityOperationType.Delete,
|
|
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
|
+
});
|
|
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({
|
|
247
579
|
entityKey: item.entityKey,
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
...(extensions ?? []).map((item) => ({
|
|
255
|
-
operationType: require_entity.EntityOperationType.Extend,
|
|
580
|
+
mutations
|
|
581
|
+
});
|
|
582
|
+
});
|
|
583
|
+
const extendOps = (extensions ?? []).map((item) => {
|
|
584
|
+
const expiry = require_expiry.resolveExpiry(item.expires, expiryContext);
|
|
585
|
+
return extendExpiryOperation({
|
|
256
586
|
entityKey: item.entityKey,
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
...(
|
|
264
|
-
|
|
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({
|
|
265
596
|
entityKey: item.entityKey,
|
|
266
|
-
payload: "0x",
|
|
267
|
-
contentType: encodeMime128(""),
|
|
268
|
-
attributes: [],
|
|
269
|
-
expiresIn: 0,
|
|
270
597
|
newOwner: item.newOwner
|
|
271
598
|
}))
|
|
272
599
|
];
|
|
273
|
-
|
|
600
|
+
if (operations.length === 0) throw new Error("No operations to perform");
|
|
601
|
+
logger$6("Sending execute with %d operations %o", operations.length, operations);
|
|
274
602
|
try {
|
|
275
603
|
const txHash = await walletClient.writeContract({
|
|
276
|
-
address:
|
|
277
|
-
abi: EXECUTE_ABI,
|
|
604
|
+
address: require_expiry.ARKIV_ADDRESS,
|
|
605
|
+
abi: EXECUTE_ABI$1,
|
|
278
606
|
functionName: "execute",
|
|
279
607
|
args: [operations],
|
|
280
608
|
account: client.account,
|
|
@@ -282,12 +610,12 @@ async function sendArkivTransaction(client, ops, txParams) {
|
|
|
282
610
|
...txParams
|
|
283
611
|
});
|
|
284
612
|
const receipt = await walletClient.waitForTransactionReceipt({ hash: txHash });
|
|
285
|
-
logger$
|
|
613
|
+
logger$6("Tx receipt %o", receipt);
|
|
286
614
|
if (receipt.status === "reverted") {
|
|
287
615
|
try {
|
|
288
616
|
await walletClient.simulateContract({
|
|
289
|
-
address:
|
|
290
|
-
abi: EXECUTE_ABI,
|
|
617
|
+
address: require_expiry.ARKIV_ADDRESS,
|
|
618
|
+
abi: EXECUTE_ABI$1,
|
|
291
619
|
functionName: "execute",
|
|
292
620
|
args: [operations],
|
|
293
621
|
account: client.account,
|
|
@@ -295,153 +623,71 @@ async function sendArkivTransaction(client, ops, txParams) {
|
|
|
295
623
|
});
|
|
296
624
|
} catch (err) {
|
|
297
625
|
const error = err;
|
|
298
|
-
const reason = error.shortMessage ?? error.cause?.details ?? "No reason provided by backend.";
|
|
626
|
+
const reason = describeEntityRevert(err) ?? error.shortMessage ?? error.cause?.details ?? "No reason provided by backend.";
|
|
299
627
|
throw new require_queryBuilder.EntityMutationError(`Transaction ${receipt.transactionHash} reverted. Reason: ${reason}`);
|
|
300
628
|
}
|
|
301
629
|
throw new require_queryBuilder.EntityMutationError(`Transaction ${receipt.transactionHash} reverted. No reason provided by backend.`);
|
|
302
630
|
}
|
|
303
631
|
return {
|
|
304
632
|
receipt,
|
|
305
|
-
|
|
633
|
+
...readAppliedOperations(receipt, {
|
|
634
|
+
creates: createOps.length,
|
|
635
|
+
extensions: extendOps.length
|
|
636
|
+
})
|
|
306
637
|
};
|
|
307
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 });
|
|
308
641
|
let message = "Transaction failed";
|
|
309
642
|
if (error instanceof viem.TransactionExecutionError) message += `: ${error.details}`;
|
|
310
643
|
else if (error instanceof viem.ContractFunctionExecutionError) {
|
|
311
|
-
logger$
|
|
644
|
+
logger$6("Contract function execution error data:", error.shortMessage);
|
|
312
645
|
if (error.cause instanceof viem.ContractFunctionRevertedError) message += `: ${error.cause.message}`;
|
|
313
646
|
else message += ": Execution error without revert data";
|
|
314
647
|
} else if (error instanceof require_queryBuilder.EntityMutationError) throw error;
|
|
315
|
-
|
|
648
|
+
else if (error instanceof Error) message += `: ${error.message}`;
|
|
649
|
+
throw new require_queryBuilder.EntityMutationError(message, { cause: error });
|
|
316
650
|
}
|
|
317
651
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
logger$6("event from subscribeEntityEvents %o", event);
|
|
337
|
-
if (event.eventName !== "EntityOperation") continue;
|
|
338
|
-
const entityKey = event.args.entityKey;
|
|
339
|
-
const owner = event.args.owner;
|
|
340
|
-
const expiresAt = event.args.expiresAt;
|
|
341
|
-
const entityHash = event.args.entityHash;
|
|
342
|
-
switch (Number(event.args.operationType)) {
|
|
343
|
-
case require_entity.EntityOperationType.Create:
|
|
344
|
-
onEntityCreated?.({
|
|
345
|
-
entityKey,
|
|
346
|
-
owner,
|
|
347
|
-
expiresAt,
|
|
348
|
-
entityHash
|
|
349
|
-
});
|
|
350
|
-
break;
|
|
351
|
-
case require_entity.EntityOperationType.Update:
|
|
352
|
-
onEntityUpdated?.({
|
|
353
|
-
entityKey,
|
|
354
|
-
owner,
|
|
355
|
-
expiresAt,
|
|
356
|
-
entityHash
|
|
357
|
-
});
|
|
358
|
-
break;
|
|
359
|
-
case require_entity.EntityOperationType.Extend:
|
|
360
|
-
onEntityExpiresInExtended?.({
|
|
361
|
-
entityKey,
|
|
362
|
-
owner,
|
|
363
|
-
expiresAt,
|
|
364
|
-
entityHash
|
|
365
|
-
});
|
|
366
|
-
break;
|
|
367
|
-
case require_entity.EntityOperationType.Transfer:
|
|
368
|
-
onEntityOwnerChanged?.({
|
|
369
|
-
entityKey,
|
|
370
|
-
owner,
|
|
371
|
-
entityHash
|
|
372
|
-
});
|
|
373
|
-
break;
|
|
374
|
-
case require_entity.EntityOperationType.Delete:
|
|
375
|
-
onEntityDeleted?.({
|
|
376
|
-
entityKey,
|
|
377
|
-
owner
|
|
378
|
-
});
|
|
379
|
-
break;
|
|
380
|
-
default:
|
|
381
|
-
onEntityExpired?.({
|
|
382
|
-
entityKey,
|
|
383
|
-
owner
|
|
384
|
-
});
|
|
385
|
-
break;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
},
|
|
389
|
-
onError: (error) => {
|
|
390
|
-
console.error("error from subscribeEntityEvents", error);
|
|
391
|
-
onError?.(error);
|
|
392
|
-
}
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
//#endregion
|
|
397
|
-
//#region src/clients/decorators/arkivPublic.ts
|
|
398
|
-
function publicArkivActions(client) {
|
|
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);
|
|
399
670
|
return {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
select: (selection) => new require_queryBuilder.SelectQueryBuilder(client, selection),
|
|
404
|
-
getBlockTiming: () => getBlockTiming(client),
|
|
405
|
-
getEntityCount: () => getEntityCount(client),
|
|
406
|
-
subscribeEntityEvents: ({ onError, onEntityCreated, onEntityUpdated, onEntityDeleted, onEntityExpired, onEntityExpiresInExtended }, pollingInterval, fromBlock) => subscribeEntityEvents(client, {
|
|
407
|
-
onError,
|
|
408
|
-
onEntityCreated,
|
|
409
|
-
onEntityUpdated,
|
|
410
|
-
onEntityDeleted,
|
|
411
|
-
onEntityExpired,
|
|
412
|
-
onEntityExpiresInExtended
|
|
413
|
-
}, pollingInterval, fromBlock)
|
|
671
|
+
createdEntityKeys,
|
|
672
|
+
createdExpiries,
|
|
673
|
+
extendedExpiries
|
|
414
674
|
};
|
|
415
675
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
* import { braga } from 'arkiv/chains'
|
|
432
|
-
*
|
|
433
|
-
* const client = createPublicClient({
|
|
434
|
-
* chain: braga,
|
|
435
|
-
* transport: http(),
|
|
436
|
-
* })
|
|
437
|
-
*/
|
|
438
|
-
function createPublicClient(parameters) {
|
|
439
|
-
const { key = "public", name = "Public Client" } = parameters;
|
|
440
|
-
return (0, viem.createClient)({
|
|
441
|
-
...parameters,
|
|
442
|
-
key,
|
|
443
|
-
name
|
|
444
|
-
}).extend(viem.publicActions).extend(publicArkivActions);
|
|
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;
|
|
686
|
+
}
|
|
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.`);
|
|
445
691
|
}
|
|
446
692
|
|
|
447
693
|
//#endregion
|
|
@@ -462,11 +708,15 @@ async function changeOwnership(client, data, txParams) {
|
|
|
462
708
|
const logger$4 = require_queryBuilder.getLogger("actions:wallet:create-entity");
|
|
463
709
|
async function createEntity(client, data, txParams) {
|
|
464
710
|
logger$4("createEntity %o", data);
|
|
465
|
-
const { receipt, createdEntityKeys } = await sendArkivTransaction(client, { creates: [data] }, txParams);
|
|
711
|
+
const { receipt, createdEntityKeys, createdExpiries } = await sendArkivTransaction(client, { creates: [data] }, txParams);
|
|
466
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.`);
|
|
467
716
|
return {
|
|
468
717
|
txHash: receipt.transactionHash,
|
|
469
|
-
entityKey
|
|
718
|
+
entityKey,
|
|
719
|
+
expiresAt
|
|
470
720
|
};
|
|
471
721
|
}
|
|
472
722
|
|
|
@@ -488,11 +738,14 @@ async function deleteEntity(client, data, txParams) {
|
|
|
488
738
|
const logger$2 = require_queryBuilder.getLogger("actions:wallet:extend-entity");
|
|
489
739
|
async function extendEntity(client, data, txParams) {
|
|
490
740
|
logger$2("extendEntity %o", data);
|
|
491
|
-
const { receipt } = await sendArkivTransaction(client, { extensions: [data] }, txParams);
|
|
741
|
+
const { receipt, extendedExpiries } = await sendArkivTransaction(client, { extensions: [data] }, txParams);
|
|
492
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.`);
|
|
493
745
|
return {
|
|
494
746
|
txHash: receipt.transactionHash,
|
|
495
|
-
entityKey: data.entityKey
|
|
747
|
+
entityKey: data.entityKey,
|
|
748
|
+
expiresAt
|
|
496
749
|
};
|
|
497
750
|
}
|
|
498
751
|
|
|
@@ -500,13 +753,12 @@ async function extendEntity(client, data, txParams) {
|
|
|
500
753
|
//#region src/actions/wallet/mutateEntities.ts
|
|
501
754
|
const logger$1 = require_queryBuilder.getLogger("actions:wallet:mutate-entities");
|
|
502
755
|
async function mutateEntities(client, data, txParams) {
|
|
503
|
-
if (!data.creates && !data.updates && !data.deletes && !data.extensions) throw new Error("No operations to perform");
|
|
504
756
|
const { receipt, createdEntityKeys } = await sendArkivTransaction(client, data, txParams);
|
|
505
757
|
logger$1("Receipt from mutateEntities %o", receipt);
|
|
506
758
|
return {
|
|
507
759
|
txHash: receipt.transactionHash,
|
|
508
760
|
createdEntities: createdEntityKeys,
|
|
509
|
-
|
|
761
|
+
patchedEntities: (data.patches ?? []).map((p) => p.entityKey),
|
|
510
762
|
deletedEntities: (data.deletes ?? []).map((d) => d.entityKey),
|
|
511
763
|
extendedEntities: (data.extensions ?? []).map((e) => e.entityKey),
|
|
512
764
|
ownershipChanges: (data.ownershipChanges ?? []).map((o) => o.entityKey)
|
|
@@ -514,12 +766,12 @@ async function mutateEntities(client, data, txParams) {
|
|
|
514
766
|
}
|
|
515
767
|
|
|
516
768
|
//#endregion
|
|
517
|
-
//#region src/actions/wallet/
|
|
518
|
-
const logger = require_queryBuilder.getLogger("actions:wallet:
|
|
519
|
-
async function
|
|
520
|
-
logger("
|
|
521
|
-
const { receipt } = await sendArkivTransaction(client, {
|
|
522
|
-
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);
|
|
523
775
|
return {
|
|
524
776
|
txHash: receipt.transactionHash,
|
|
525
777
|
entityKey: data.entityKey
|
|
@@ -531,7 +783,7 @@ async function updateEntity(client, data, txParams) {
|
|
|
531
783
|
function walletArkivActions(client) {
|
|
532
784
|
return {
|
|
533
785
|
createEntity: (data, txParams) => createEntity(client, data, txParams),
|
|
534
|
-
|
|
786
|
+
patchEntity: (data, txParams) => patchEntity(client, data, txParams),
|
|
535
787
|
deleteEntity: (data, txParams) => deleteEntity(client, data, txParams),
|
|
536
788
|
extendEntity: (data, txParams) => extendEntity(client, data, txParams),
|
|
537
789
|
changeOwnership: (data, txParams) => changeOwnership(client, data, txParams),
|
|
@@ -542,36 +794,42 @@ function walletArkivActions(client) {
|
|
|
542
794
|
//#endregion
|
|
543
795
|
//#region src/clients/createWalletClient.ts
|
|
544
796
|
/**
|
|
545
|
-
* 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.
|
|
546
799
|
*
|
|
547
|
-
* - Docs: https://docs.arkiv.network/ts-sdk/clients/
|
|
800
|
+
* - Docs: https://docs.arkiv.network/ts-sdk/clients/wallet
|
|
548
801
|
*
|
|
549
|
-
* 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.
|
|
550
805
|
*
|
|
551
806
|
* @param parameters - Configuration object for the wallet client (chain, transport, account, etc.)
|
|
552
807
|
* @returns A Arkiv Wallet Client. {@link WalletArkivClient}
|
|
553
808
|
*
|
|
554
809
|
* @example
|
|
555
|
-
* import {
|
|
556
|
-
* 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"
|
|
557
814
|
*
|
|
558
|
-
* const client =
|
|
559
|
-
* chain:
|
|
815
|
+
* const client = createWalletClient({
|
|
816
|
+
* chain: cheesecake,
|
|
560
817
|
* transport: http(),
|
|
818
|
+
* account: privateKeyToAccount("0x..."),
|
|
561
819
|
* })
|
|
562
820
|
*/
|
|
563
821
|
function createWalletClient(parameters) {
|
|
564
|
-
const { key = "wallet", name = "Wallet Client" } = parameters;
|
|
822
|
+
const { key: key$1 = "wallet", name = "Wallet Client" } = parameters;
|
|
565
823
|
return (0, viem.createClient)({
|
|
566
824
|
...parameters,
|
|
567
|
-
key,
|
|
825
|
+
key: key$1,
|
|
568
826
|
name
|
|
569
827
|
}).extend(viem.publicActions).extend(viem.walletActions).extend(walletArkivActions);
|
|
570
828
|
}
|
|
571
829
|
|
|
572
830
|
//#endregion
|
|
573
831
|
//#region src/utils/chains.ts
|
|
574
|
-
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]));
|
|
575
833
|
/**
|
|
576
834
|
* Get a chain from its name
|
|
577
835
|
* @param name - The name of the chain, case insensitive
|
|
@@ -585,18 +843,61 @@ function chainFromName(name) {
|
|
|
585
843
|
}
|
|
586
844
|
|
|
587
845
|
//#endregion
|
|
588
|
-
exports.
|
|
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;
|
|
589
852
|
exports.EntityMutationError = require_queryBuilder.EntityMutationError;
|
|
590
|
-
exports.
|
|
591
|
-
exports.
|
|
592
|
-
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;
|
|
593
857
|
exports.InvalidContentTypeError = require_queryBuilder.InvalidContentTypeError;
|
|
594
|
-
exports.
|
|
595
|
-
exports.
|
|
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;
|
|
596
869
|
exports.NoEntityFoundError = require_queryBuilder.NoEntityFoundError;
|
|
597
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;
|
|
598
881
|
exports.chainFromName = chainFromName;
|
|
599
882
|
exports.createPublicClient = createPublicClient;
|
|
600
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;
|
|
601
892
|
exports.jsonToPayload = require_payload.jsonToPayload;
|
|
602
|
-
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;
|