@arkiv-network/sdk 0.6.8 → 0.7.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 +52 -16
- package/dist/consts-Bz0LZQZY.js +7 -0
- package/dist/consts-Bz0LZQZY.js.map +1 -0
- package/dist/consts-CxT1-RXU.cjs +18 -0
- package/dist/entity-BhSXaB23.cjs +81 -0
- package/dist/{query-CO6f35AE.d.cts → entity-CN41IOrq.d.cts} +125 -59
- package/dist/entity-CN41IOrq.d.cts.map +1 -0
- package/dist/entity-DGfVyB-a.js +71 -0
- package/dist/entity-DGfVyB-a.js.map +1 -0
- package/dist/{query-BhdmAzYg.d.ts → entity-NnEVlePN.d.ts} +125 -59
- package/dist/entity-NnEVlePN.d.ts.map +1 -0
- package/dist/index-ClkpS6s_.d.ts +481 -0
- package/dist/index-ClkpS6s_.d.ts.map +1 -0
- package/dist/index-w4qop0Pe.d.cts +481 -0
- package/dist/index-w4qop0Pe.d.cts.map +1 -0
- package/dist/index.cjs +285 -233
- package/dist/index.d.cts +100 -6
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +101 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +280 -230
- package/dist/index.js.map +1 -1
- package/dist/payload-BpNUPOnY.js +13 -0
- package/dist/payload-BpNUPOnY.js.map +1 -0
- package/dist/{payload-Da9gJMG5.d.ts → payload-C2KHOUoj.d.ts} +1 -1
- package/dist/{payload-Da9gJMG5.d.ts.map → payload-C2KHOUoj.d.ts.map} +1 -1
- package/dist/{payload-vwU3Rc6P.cjs → payload-D8YLKcJj.cjs} +1 -18
- package/dist/query/index.cjs +11 -28
- package/dist/query/index.d.cts +3 -3
- package/dist/query/index.d.ts +3 -3
- package/dist/query/index.js +8 -28
- package/dist/query/index.js.map +1 -1
- package/dist/{queryBuilder-DonAg1aq.js → queryBuilder-BE_XhLLa.js} +303 -152
- package/dist/queryBuilder-BE_XhLLa.js.map +1 -0
- package/dist/{queryBuilder-DM-YO1Y7.cjs → queryBuilder-J37buGCi.cjs} +372 -149
- package/dist/types/index.cjs +4 -1
- package/dist/types/index.d.cts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +4 -1
- package/dist/utils/index.cjs +4 -10
- package/dist/utils/index.d.cts +0 -1
- package/dist/utils/index.d.cts.map +1 -1
- package/dist/utils/index.d.ts +1 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -3
- package/dist/utils/index.js.map +1 -1
- package/package.json +11 -15
- package/src/actions/public/buildQuery.ts +4 -0
- package/src/actions/public/query.ts +10 -0
- package/src/actions/public/subscribeEntityEvents.ts +25 -51
- package/src/actions/wallet/changeOwnership.ts +6 -6
- package/src/actions/wallet/createEntity.ts +19 -6
- package/src/actions/wallet/deleteEntity.ts +2 -3
- package/src/actions/wallet/extendEntity.ts +9 -5
- package/src/actions/wallet/mutateEntities.ts +11 -54
- package/src/actions/wallet/updateEntity.ts +15 -6
- package/src/clients/createPublicClient.test.ts +2 -0
- package/src/clients/decorators/arkivPublic.ts +67 -2
- package/src/clients/decorators/arkivWallet.ts +23 -1
- package/src/consts.ts +2 -1
- package/src/errors.ts +46 -0
- package/src/index.ts +0 -3
- package/src/query/engine.test.ts +45 -0
- package/src/query/engine.ts +28 -14
- package/src/query/index.ts +1 -0
- package/src/query/predicate.test.ts +43 -0
- package/src/query/predicate.ts +14 -10
- package/src/query/queryBuilder.test.ts +22 -0
- package/src/query/queryBuilder.ts +221 -106
- package/src/query/queryResult.ts +13 -7
- package/src/query/selectQueryBuilder.test.ts +213 -0
- package/src/query/selection.test.ts +120 -0
- package/src/query/selection.ts +116 -0
- package/src/types/attributes.ts +25 -1
- package/src/types/entity.ts +12 -2
- package/src/types/events.ts +14 -16
- package/src/types/index.ts +1 -0
- package/src/types/rpcSchema.ts +7 -2
- package/src/utils/arkivTransactions.test.ts +260 -0
- package/src/utils/arkivTransactions.ts +255 -92
- package/src/utils/entities.ts +17 -7
- package/src/utils/index.ts +0 -1
- package/src/utils/payload.ts +4 -2
- package/src/utils/validation.test.ts +106 -0
- package/src/utils/validation.ts +80 -0
- package/dist/accounts/index.cjs +0 -9
- package/dist/accounts/index.d.cts +0 -1
- package/dist/accounts/index.d.ts +0 -1
- package/dist/accounts/index.js +0 -1
- package/dist/payload-DKBYYjeA.js +0 -18
- package/dist/payload-DKBYYjeA.js.map +0 -1
- package/dist/query-BhdmAzYg.d.ts.map +0 -1
- package/dist/query-CO6f35AE.d.cts.map +0 -1
- package/dist/queryBuilder-BvoQXa_u.d.ts +0 -328
- package/dist/queryBuilder-BvoQXa_u.d.ts.map +0 -1
- package/dist/queryBuilder-DonAg1aq.js.map +0 -1
- package/dist/queryBuilder-zTsKXctT.d.cts +0 -328
- package/dist/queryBuilder-zTsKXctT.d.cts.map +0 -1
- package/src/accounts/index.ts +0 -1
- /package/dist/{types-H-TSmRpm.js → types-Ci4BRClw.js} +0 -0
- /package/dist/{types-o3zWarRp.cjs → types-a8gm_IaQ.cjs} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { t as chains_exports } from "./chains-CrtkVbBh.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import "./
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
import { S as getLogger, _ as InvalidContentTypeError, b as NoEntityFoundError, c as isEntityKey, d as entityFromRpcResult, f as RpcAttributeValueType, g as InvalidAttributeKeyError, h as InvalidAttributeError, l as validateAttribute, m as EntityMutationError, n as QueryBuilder, p as DuplicateAttributeError, r as SelectQueryBuilder, u as validateExpiresIn, v as InvalidExpirationError, x as NoMoreResultsError, y as NoCursorOrLimitError } from "./queryBuilder-BE_XhLLa.js";
|
|
3
|
+
import { n as BLOCK_TIME, t as ARKIV_ADDRESS } from "./consts-Bz0LZQZY.js";
|
|
4
|
+
import { n as EntityOperationType } from "./entity-DGfVyB-a.js";
|
|
5
|
+
import "./types-Ci4BRClw.js";
|
|
6
|
+
import { n as stringToPayload, t as jsonToPayload } from "./payload-BpNUPOnY.js";
|
|
7
|
+
import { ContractFunctionExecutionError, ContractFunctionRevertedError, TransactionExecutionError, bytesToHex, createClient, decodeEventLog, encodePacked, hexToBytes, keccak256, numberToHex, parseAbi, publicActions, stringToBytes, toBytes, toHex, walletActions } from "viem";
|
|
8
8
|
|
|
9
9
|
//#region src/actions/public/getBlockTiming.ts
|
|
10
|
-
const logger$
|
|
10
|
+
const logger$8 = getLogger("actions:public:get-block-timing");
|
|
11
11
|
async function getBlockTiming(client) {
|
|
12
12
|
const blockTiming = await client.request({
|
|
13
13
|
method: "arkiv_getBlockTiming",
|
|
14
14
|
params: []
|
|
15
15
|
});
|
|
16
|
-
logger$
|
|
16
|
+
logger$8("Block timing %o", blockTiming);
|
|
17
17
|
return {
|
|
18
18
|
currentBlock: BigInt(blockTiming.current_block),
|
|
19
19
|
currentBlockTime: blockTiming.current_block_time,
|
|
@@ -99,78 +99,289 @@ async function query(client, query$1, queryOptions) {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
//#endregion
|
|
102
|
-
//#region src/
|
|
103
|
-
const logger$
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
102
|
+
//#region src/utils/arkivTransactions.ts
|
|
103
|
+
const logger$7 = getLogger("utils:arkiv-transactions");
|
|
104
|
+
const MIME_REGEX = /^[a-z][a-z0-9!#$&\-^_]*\/[a-z0-9][a-z0-9!#$&\-^_.+]*$/;
|
|
105
|
+
function validateContentType(contentType) {
|
|
106
|
+
if (!MIME_REGEX.test(contentType)) throw new InvalidContentTypeError(contentType);
|
|
107
|
+
}
|
|
108
|
+
const ENTITY_EXECUTE_ABI = 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 = parseAbi(["event EntityOperation(bytes32 indexed entityKey, uint8 indexed operationType, address indexed owner, uint32 expiresAt, bytes32 entityHash)"]);
|
|
110
|
+
const ENTITY_ERRORS_ABI = parseAbi([
|
|
111
|
+
"error EmptyBatch()",
|
|
112
|
+
"error AttributesNotSorted()",
|
|
113
|
+
"error InvalidValueType(bytes32 name, uint8 valueType)",
|
|
114
|
+
"error InvalidOpType(uint8 operationType)",
|
|
115
|
+
"error ExpiryInPast(uint32 expiresAt, uint32 currentBlock)",
|
|
116
|
+
"error TooManyAttributes(uint256 count, uint256 maxCount)",
|
|
117
|
+
"error EntityNotFound(bytes32 entityKey)",
|
|
118
|
+
"error NotOwner(bytes32 entityKey, address caller, address owner)",
|
|
119
|
+
"error EntityExpired(bytes32 entityKey, uint32 expiresAt)",
|
|
120
|
+
"error ExpiryNotExtended(bytes32 entityKey, uint32 newExpiresAt, uint32 currentExpiresAt)",
|
|
121
|
+
"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()"
|
|
111
131
|
]);
|
|
132
|
+
const EXECUTE_ABI = [...ENTITY_EXECUTE_ABI, ...ENTITY_ERRORS_ABI];
|
|
133
|
+
const ENTITY_NONCE_ABI = 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
|
+
toHex(padded.slice(0, 32)),
|
|
147
|
+
toHex(padded.slice(32, 64)),
|
|
148
|
+
toHex(padded.slice(64, 96)),
|
|
149
|
+
toHex(padded.slice(96, 128))
|
|
150
|
+
];
|
|
151
|
+
}
|
|
152
|
+
function encodeMime128(contentType) {
|
|
153
|
+
return { data: contentType ? encodeBytes128(stringToBytes(contentType)) : EMPTY_BYTES128 };
|
|
154
|
+
}
|
|
155
|
+
function encodeAttribute(attr) {
|
|
156
|
+
validateAttribute(attr);
|
|
157
|
+
const name = toHex(attr.key, { size: 32 });
|
|
158
|
+
if (typeof attr.value === "string") {
|
|
159
|
+
if (isEntityKey(attr.value)) return {
|
|
160
|
+
name,
|
|
161
|
+
valueType: RpcAttributeValueType.EntityKey,
|
|
162
|
+
value: [
|
|
163
|
+
toHex(toBytes(attr.value), { size: 32 }),
|
|
164
|
+
ZERO_32,
|
|
165
|
+
ZERO_32,
|
|
166
|
+
ZERO_32
|
|
167
|
+
]
|
|
168
|
+
};
|
|
169
|
+
return {
|
|
170
|
+
name,
|
|
171
|
+
valueType: RpcAttributeValueType.String,
|
|
172
|
+
value: encodeBytes128(stringToBytes(attr.value))
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
name,
|
|
177
|
+
valueType: RpcAttributeValueType.Uint,
|
|
178
|
+
value: [
|
|
179
|
+
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 DuplicateAttributeError(encoded[i].key);
|
|
192
|
+
return encoded.map(({ key: _,...attr }) => attr);
|
|
193
|
+
}
|
|
194
|
+
function toBTL(expiresIn) {
|
|
195
|
+
validateExpiresIn(expiresIn);
|
|
196
|
+
return Math.ceil(expiresIn / BLOCK_TIME);
|
|
197
|
+
}
|
|
198
|
+
function deriveEntityKey(chainId, owner, nonce) {
|
|
199
|
+
return keccak256(encodePacked([
|
|
200
|
+
"uint256",
|
|
201
|
+
"address",
|
|
202
|
+
"address",
|
|
203
|
+
"uint32"
|
|
204
|
+
], [
|
|
205
|
+
BigInt(chainId),
|
|
206
|
+
ARKIV_ADDRESS,
|
|
207
|
+
owner,
|
|
208
|
+
Number(nonce)
|
|
209
|
+
]));
|
|
210
|
+
}
|
|
211
|
+
async function sendArkivTransaction(client, ops, txParams) {
|
|
212
|
+
if (!client.account) throw new Error("Account required");
|
|
213
|
+
if (!client.chain) throw new Error("Chain required");
|
|
214
|
+
const walletClient = client;
|
|
215
|
+
const { creates, updates, deletes, extensions, ownershipChanges } = ops;
|
|
216
|
+
const owner = client.account.address;
|
|
217
|
+
const ownerNonce = creates?.length ? BigInt(await walletClient.readContract({
|
|
218
|
+
address: ARKIV_ADDRESS,
|
|
219
|
+
abi: ENTITY_NONCE_ABI,
|
|
220
|
+
functionName: "nonces",
|
|
221
|
+
args: [owner]
|
|
222
|
+
})) : 0n;
|
|
223
|
+
const createdEntityKeys = (creates ?? []).map((_, i) => deriveEntityKey(client.chain.id, owner, ownerNonce + BigInt(i)));
|
|
224
|
+
for (const item of creates ?? []) validateContentType(item.contentType);
|
|
225
|
+
for (const item of updates ?? []) validateContentType(item.contentType);
|
|
226
|
+
const operations = [
|
|
227
|
+
...(creates ?? []).map((item, i) => ({
|
|
228
|
+
operationType: EntityOperationType.Create,
|
|
229
|
+
entityKey: createdEntityKeys[i],
|
|
230
|
+
payload: toHex(item.payload),
|
|
231
|
+
contentType: encodeMime128(item.contentType),
|
|
232
|
+
attributes: encodeAttributes(item.attributes),
|
|
233
|
+
expiresIn: toBTL(item.expiresIn),
|
|
234
|
+
newOwner: ZERO_ADDRESS
|
|
235
|
+
})),
|
|
236
|
+
...(updates ?? []).map((item) => ({
|
|
237
|
+
operationType: EntityOperationType.Update,
|
|
238
|
+
entityKey: item.entityKey,
|
|
239
|
+
payload: 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: EntityOperationType.Delete,
|
|
247
|
+
entityKey: item.entityKey,
|
|
248
|
+
payload: "0x",
|
|
249
|
+
contentType: encodeMime128(""),
|
|
250
|
+
attributes: [],
|
|
251
|
+
expiresIn: 0,
|
|
252
|
+
newOwner: ZERO_ADDRESS
|
|
253
|
+
})),
|
|
254
|
+
...(extensions ?? []).map((item) => ({
|
|
255
|
+
operationType: EntityOperationType.Extend,
|
|
256
|
+
entityKey: item.entityKey,
|
|
257
|
+
payload: "0x",
|
|
258
|
+
contentType: encodeMime128(""),
|
|
259
|
+
attributes: [],
|
|
260
|
+
expiresIn: toBTL(item.expiresIn),
|
|
261
|
+
newOwner: ZERO_ADDRESS
|
|
262
|
+
})),
|
|
263
|
+
...(ownershipChanges ?? []).map((item) => ({
|
|
264
|
+
operationType: EntityOperationType.Transfer,
|
|
265
|
+
entityKey: item.entityKey,
|
|
266
|
+
payload: "0x",
|
|
267
|
+
contentType: encodeMime128(""),
|
|
268
|
+
attributes: [],
|
|
269
|
+
expiresIn: 0,
|
|
270
|
+
newOwner: item.newOwner
|
|
271
|
+
}))
|
|
272
|
+
];
|
|
273
|
+
logger$7("Sending execute with %d operations %s", operations.length, JSON.stringify(operations));
|
|
274
|
+
try {
|
|
275
|
+
const txHash = await walletClient.writeContract({
|
|
276
|
+
address: ARKIV_ADDRESS,
|
|
277
|
+
abi: EXECUTE_ABI,
|
|
278
|
+
functionName: "execute",
|
|
279
|
+
args: [operations],
|
|
280
|
+
account: client.account,
|
|
281
|
+
chain: client.chain,
|
|
282
|
+
...txParams
|
|
283
|
+
});
|
|
284
|
+
const receipt = await walletClient.waitForTransactionReceipt({ hash: txHash });
|
|
285
|
+
logger$7("Tx receipt %o", receipt);
|
|
286
|
+
if (receipt.status === "reverted") {
|
|
287
|
+
try {
|
|
288
|
+
await walletClient.simulateContract({
|
|
289
|
+
address: ARKIV_ADDRESS,
|
|
290
|
+
abi: EXECUTE_ABI,
|
|
291
|
+
functionName: "execute",
|
|
292
|
+
args: [operations],
|
|
293
|
+
account: client.account,
|
|
294
|
+
chain: client.chain
|
|
295
|
+
});
|
|
296
|
+
} catch (err) {
|
|
297
|
+
const error = err;
|
|
298
|
+
const reason = error.shortMessage ?? error.cause?.details ?? "No reason provided by backend.";
|
|
299
|
+
throw new EntityMutationError(`Transaction ${receipt.transactionHash} reverted. Reason: ${reason}`);
|
|
300
|
+
}
|
|
301
|
+
throw new EntityMutationError(`Transaction ${receipt.transactionHash} reverted. No reason provided by backend.`);
|
|
302
|
+
}
|
|
303
|
+
return {
|
|
304
|
+
receipt,
|
|
305
|
+
createdEntityKeys
|
|
306
|
+
};
|
|
307
|
+
} catch (error) {
|
|
308
|
+
let message = "Transaction failed";
|
|
309
|
+
if (error instanceof TransactionExecutionError) message += `: ${error.details}`;
|
|
310
|
+
else if (error instanceof ContractFunctionExecutionError) {
|
|
311
|
+
logger$7("Contract function execution error data:", error.shortMessage);
|
|
312
|
+
if (error.cause instanceof ContractFunctionRevertedError) message += `: ${error.cause.message}`;
|
|
313
|
+
else message += ": Execution error without revert data";
|
|
314
|
+
} else if (error instanceof EntityMutationError) throw error;
|
|
315
|
+
throw new EntityMutationError(message);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
//#endregion
|
|
320
|
+
//#region src/actions/public/subscribeEntityEvents.ts
|
|
321
|
+
const logger$6 = getLogger("actions:public:subscribe-entity-events");
|
|
322
|
+
const arkivABI = ENTITY_OPERATION_EVENT_ABI;
|
|
112
323
|
async function subscribeEntityEvents(client, { onError, onEntityCreated, onEntityUpdated, onEntityDeleted, onEntityExpired, onEntityExpiresInExtended, onEntityOwnerChanged }, pollingInterval, fromBlock) {
|
|
113
324
|
return client.watchEvent({
|
|
114
325
|
pollingInterval: pollingInterval ?? 1e3,
|
|
115
326
|
fromBlock,
|
|
116
327
|
events: arkivABI,
|
|
117
328
|
onLogs: (logs) => {
|
|
118
|
-
logger$
|
|
329
|
+
logger$6("logs from subscribeEntityEvents %o", logs);
|
|
119
330
|
for (const log of logs) {
|
|
120
331
|
const event = decodeEventLog({
|
|
121
332
|
abi: arkivABI,
|
|
122
333
|
topics: log.topics,
|
|
123
334
|
data: log.data
|
|
124
335
|
});
|
|
125
|
-
logger$
|
|
126
|
-
|
|
127
|
-
|
|
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 EntityOperationType.Create:
|
|
128
344
|
onEntityCreated?.({
|
|
129
|
-
entityKey
|
|
130
|
-
owner
|
|
131
|
-
|
|
132
|
-
|
|
345
|
+
entityKey,
|
|
346
|
+
owner,
|
|
347
|
+
expiresAt,
|
|
348
|
+
entityHash
|
|
133
349
|
});
|
|
134
350
|
break;
|
|
135
|
-
case
|
|
351
|
+
case EntityOperationType.Update:
|
|
136
352
|
onEntityUpdated?.({
|
|
137
|
-
entityKey
|
|
138
|
-
owner
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
cost: event.args.cost
|
|
142
|
-
});
|
|
143
|
-
break;
|
|
144
|
-
case "ArkivEntityDeleted":
|
|
145
|
-
onEntityDeleted?.({
|
|
146
|
-
entityKey: toHex(event.args.entityKey, { size: 32 }),
|
|
147
|
-
owner: event.args.ownerAddress
|
|
353
|
+
entityKey,
|
|
354
|
+
owner,
|
|
355
|
+
expiresAt,
|
|
356
|
+
entityHash
|
|
148
357
|
});
|
|
149
358
|
break;
|
|
150
|
-
case
|
|
359
|
+
case EntityOperationType.Extend:
|
|
151
360
|
onEntityExpiresInExtended?.({
|
|
152
|
-
entityKey
|
|
153
|
-
owner
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
cost: event.args.cost
|
|
361
|
+
entityKey,
|
|
362
|
+
owner,
|
|
363
|
+
expiresAt,
|
|
364
|
+
entityHash
|
|
157
365
|
});
|
|
158
366
|
break;
|
|
159
|
-
case
|
|
160
|
-
|
|
161
|
-
entityKey
|
|
162
|
-
owner
|
|
367
|
+
case EntityOperationType.Transfer:
|
|
368
|
+
onEntityOwnerChanged?.({
|
|
369
|
+
entityKey,
|
|
370
|
+
owner,
|
|
371
|
+
entityHash
|
|
163
372
|
});
|
|
164
373
|
break;
|
|
165
|
-
case
|
|
166
|
-
|
|
167
|
-
entityKey
|
|
168
|
-
|
|
169
|
-
newOwner: event.args.newOwnerAddress
|
|
374
|
+
case EntityOperationType.Delete:
|
|
375
|
+
onEntityDeleted?.({
|
|
376
|
+
entityKey,
|
|
377
|
+
owner
|
|
170
378
|
});
|
|
171
379
|
break;
|
|
172
380
|
default:
|
|
173
|
-
|
|
381
|
+
onEntityExpired?.({
|
|
382
|
+
entityKey,
|
|
383
|
+
owner
|
|
384
|
+
});
|
|
174
385
|
break;
|
|
175
386
|
}
|
|
176
387
|
}
|
|
@@ -189,6 +400,7 @@ function publicArkivActions(client) {
|
|
|
189
400
|
getEntity: (key) => getEntity(client, key),
|
|
190
401
|
query: (rawQuery, queryOptions) => query(client, rawQuery, queryOptions),
|
|
191
402
|
buildQuery: () => new QueryBuilder(client),
|
|
403
|
+
select: (selection) => new SelectQueryBuilder(client, selection),
|
|
192
404
|
getBlockTiming: () => getBlockTiming(client),
|
|
193
405
|
getEntityCount: () => getEntityCount(client),
|
|
194
406
|
subscribeEntityEvents: ({ onError, onEntityCreated, onEntityUpdated, onEntityDeleted, onEntityExpired, onEntityExpiresInExtended }, pollingInterval, fromBlock) => subscribeEntityEvents(client, {
|
|
@@ -232,141 +444,12 @@ function createPublicClient(parameters) {
|
|
|
232
444
|
}).extend(publicActions).extend(publicArkivActions);
|
|
233
445
|
}
|
|
234
446
|
|
|
235
|
-
//#endregion
|
|
236
|
-
//#region src/utils/compression.ts
|
|
237
|
-
const logger$7 = getLogger("utils:compression");
|
|
238
|
-
const isNode = typeof process !== "undefined" && process.versions?.node != null;
|
|
239
|
-
let zlib = null;
|
|
240
|
-
let brotli = null;
|
|
241
|
-
async function getZlib() {
|
|
242
|
-
if (!isNode) return null;
|
|
243
|
-
if (!zlib) try {
|
|
244
|
-
zlib = await import("zlib");
|
|
245
|
-
} catch (error) {
|
|
246
|
-
console.error("Error importing zlib", error);
|
|
247
|
-
return null;
|
|
248
|
-
}
|
|
249
|
-
return zlib;
|
|
250
|
-
}
|
|
251
|
-
async function getBrotli() {
|
|
252
|
-
if (brotli) return brotli;
|
|
253
|
-
try {
|
|
254
|
-
const brotliModule = await import("brotli-wasm");
|
|
255
|
-
brotli = brotliModule.default ? await brotliModule.default : brotliModule;
|
|
256
|
-
} catch (error) {
|
|
257
|
-
console.error("Error importing brotli-wasm", error);
|
|
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);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
const brotliInstance = await getBrotli();
|
|
277
|
-
if (!brotliInstance) {
|
|
278
|
-
console.warn("Brotli instance not found, not compressing data");
|
|
279
|
-
return data;
|
|
280
|
-
}
|
|
281
|
-
const brotliCompressed = brotliInstance.compress(data);
|
|
282
|
-
logger$7("Brotli compressed with wasm size %d", brotliCompressed.length);
|
|
283
|
-
return brotliCompressed;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
//#endregion
|
|
287
|
-
//#region src/utils/arkivTransactions.ts
|
|
288
|
-
const logger$6 = getLogger("utils:arkiv-transactions");
|
|
289
|
-
function opsToTxData({ creates, updates, deletes, extensions, ownershipChanges }) {
|
|
290
|
-
function formatAttributes(attribute) {
|
|
291
|
-
return [toHex(attribute.key), toHex(typeof attribute.value === "number" && attribute.value === 0 ? "" : attribute.value)];
|
|
292
|
-
}
|
|
293
|
-
const payload = [
|
|
294
|
-
(creates ?? []).map((item) => [
|
|
295
|
-
toHex(Math.ceil(item.expiresIn / BLOCK_TIME)),
|
|
296
|
-
toHex(item.contentType),
|
|
297
|
-
toHex(item.payload),
|
|
298
|
-
item.attributes.filter((attribute) => typeof attribute.value === "string").map(formatAttributes),
|
|
299
|
-
item.attributes.filter((attribute) => typeof attribute.value === "number").map(formatAttributes)
|
|
300
|
-
]),
|
|
301
|
-
(updates ?? []).map((item) => [
|
|
302
|
-
item.entityKey,
|
|
303
|
-
toHex(item.contentType),
|
|
304
|
-
toHex(Math.ceil(item.expiresIn / BLOCK_TIME)),
|
|
305
|
-
toHex(item.payload),
|
|
306
|
-
item.attributes.filter((attribute) => typeof attribute.value === "string").map(formatAttributes),
|
|
307
|
-
item.attributes.filter((attribute) => typeof attribute.value === "number").map(formatAttributes)
|
|
308
|
-
]),
|
|
309
|
-
(deletes ?? []).map((item) => item.entityKey),
|
|
310
|
-
(extensions ?? []).map((item) => [item.entityKey, toHex(Math.ceil(item.expiresIn / BLOCK_TIME))]),
|
|
311
|
-
(ownershipChanges ?? []).map((item) => [item.entityKey, item.newOwner])
|
|
312
|
-
];
|
|
313
|
-
logger$6("txData to send as RLP %o length %d", payload, payload.length);
|
|
314
|
-
return toRlp(payload);
|
|
315
|
-
}
|
|
316
|
-
async function sendArkivTransaction(client, data, txParams) {
|
|
317
|
-
if (!client.account) throw new Error("Account required");
|
|
318
|
-
const walletClient = client;
|
|
319
|
-
logger$6("Sending transaction %o", {
|
|
320
|
-
account: client.account,
|
|
321
|
-
chain: client.chain,
|
|
322
|
-
to: ARKIV_ADDRESS,
|
|
323
|
-
value: 0n,
|
|
324
|
-
data,
|
|
325
|
-
...txParams
|
|
326
|
-
});
|
|
327
|
-
try {
|
|
328
|
-
const compressed = await compress(toBytes(data));
|
|
329
|
-
const txHash = await walletClient.sendTransaction({
|
|
330
|
-
account: client.account,
|
|
331
|
-
chain: client.chain,
|
|
332
|
-
to: ARKIV_ADDRESS,
|
|
333
|
-
value: 0n,
|
|
334
|
-
data: toHex(compressed),
|
|
335
|
-
...txParams
|
|
336
|
-
});
|
|
337
|
-
const receipt = await walletClient.waitForTransactionReceipt({ hash: txHash });
|
|
338
|
-
logger$6("Tx receipt %o", receipt);
|
|
339
|
-
if (receipt.status === "reverted") try {
|
|
340
|
-
const callResult = await walletClient.call({
|
|
341
|
-
account: client.account,
|
|
342
|
-
to: ARKIV_ADDRESS,
|
|
343
|
-
value: 0n,
|
|
344
|
-
data: toHex(compressed),
|
|
345
|
-
...txParams
|
|
346
|
-
});
|
|
347
|
-
throw new EntityMutationError(`Transaction ${receipt.transactionHash} reverted. Please make sure the data for entities doesn't contain invalid characters or invalid data types.
|
|
348
|
-
Reason: ${callResult.data ? hexToString(callResult.data) : "No reason provided by backend."}`);
|
|
349
|
-
} catch (err) {
|
|
350
|
-
const reason = err.cause?.details ?? "No reason provided by backend.";
|
|
351
|
-
logger$6("Error while calling to get more details about reverted transaction. Reason: %s", reason);
|
|
352
|
-
throw new EntityMutationError(`Transaction ${receipt.transactionHash} reverted. Reason: ${reason}`);
|
|
353
|
-
}
|
|
354
|
-
return receipt;
|
|
355
|
-
} catch (error) {
|
|
356
|
-
let message = "Transaction failed";
|
|
357
|
-
if (error instanceof TransactionExecutionError) message += `: ${error.details}`;
|
|
358
|
-
else if (error instanceof EntityMutationError) throw error;
|
|
359
|
-
logger$6("%s Detailed error stack: %o", message, error);
|
|
360
|
-
throw new EntityMutationError(message);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
447
|
//#endregion
|
|
365
448
|
//#region src/actions/wallet/changeOwnership.ts
|
|
366
449
|
const logger$5 = getLogger("actions:wallet:change-ownership");
|
|
367
450
|
async function changeOwnership(client, data, txParams) {
|
|
368
451
|
logger$5("changeOwnership %o", data);
|
|
369
|
-
const receipt = await sendArkivTransaction(client,
|
|
452
|
+
const { receipt } = await sendArkivTransaction(client, { ownershipChanges: [data] }, txParams);
|
|
370
453
|
logger$5("Receipt from changeOwnership %o", receipt);
|
|
371
454
|
return {
|
|
372
455
|
txHash: receipt.transactionHash,
|
|
@@ -379,11 +462,11 @@ async function changeOwnership(client, data, txParams) {
|
|
|
379
462
|
const logger$4 = getLogger("actions:wallet:create-entity");
|
|
380
463
|
async function createEntity(client, data, txParams) {
|
|
381
464
|
logger$4("createEntity %o", data);
|
|
382
|
-
const receipt = await sendArkivTransaction(client,
|
|
465
|
+
const { receipt, createdEntityKeys } = await sendArkivTransaction(client, { creates: [data] }, txParams);
|
|
383
466
|
logger$4("Receipt from createEntity %o", receipt);
|
|
384
467
|
return {
|
|
385
468
|
txHash: receipt.transactionHash,
|
|
386
|
-
entityKey:
|
|
469
|
+
entityKey: createdEntityKeys[0]
|
|
387
470
|
};
|
|
388
471
|
}
|
|
389
472
|
|
|
@@ -392,7 +475,7 @@ async function createEntity(client, data, txParams) {
|
|
|
392
475
|
const logger$3 = getLogger("actions:wallet:delete-entity");
|
|
393
476
|
async function deleteEntity(client, data, txParams) {
|
|
394
477
|
logger$3("deleteEntity %o", data);
|
|
395
|
-
const receipt = await sendArkivTransaction(client,
|
|
478
|
+
const { receipt } = await sendArkivTransaction(client, { deletes: [data] }, txParams);
|
|
396
479
|
logger$3("Receipt from deleteEntity %o", receipt);
|
|
397
480
|
return {
|
|
398
481
|
txHash: receipt.transactionHash,
|
|
@@ -405,61 +488,28 @@ async function deleteEntity(client, data, txParams) {
|
|
|
405
488
|
const logger$2 = getLogger("actions:wallet:extend-entity");
|
|
406
489
|
async function extendEntity(client, data, txParams) {
|
|
407
490
|
logger$2("extendEntity %o", data);
|
|
408
|
-
const receipt = await sendArkivTransaction(client,
|
|
491
|
+
const { receipt } = await sendArkivTransaction(client, { extensions: [data] }, txParams);
|
|
409
492
|
logger$2("Receipt from extendEntity %o", receipt);
|
|
410
493
|
return {
|
|
411
494
|
txHash: receipt.transactionHash,
|
|
412
|
-
entityKey:
|
|
495
|
+
entityKey: data.entityKey
|
|
413
496
|
};
|
|
414
497
|
}
|
|
415
498
|
|
|
416
499
|
//#endregion
|
|
417
500
|
//#region src/actions/wallet/mutateEntities.ts
|
|
418
501
|
const logger$1 = getLogger("actions:wallet:mutate-entities");
|
|
419
|
-
function parseReceipt(receipt, params) {
|
|
420
|
-
const createdEntities = [];
|
|
421
|
-
const updatedEntities = [];
|
|
422
|
-
const deletedEntities = [];
|
|
423
|
-
const extendedEntities = [];
|
|
424
|
-
const ownershipChanges = [];
|
|
425
|
-
const totalCreates = params.creates?.length ?? 0;
|
|
426
|
-
const totalUpdates = params.updates?.length ?? 0;
|
|
427
|
-
const totalDeletes = params.deletes?.length ?? 0;
|
|
428
|
-
const totalExtensions = params.extensions?.length ?? 0;
|
|
429
|
-
for (let index = 0; index < receipt.logs.length; index++) {
|
|
430
|
-
const log = receipt.logs[index];
|
|
431
|
-
if (index < totalCreates) createdEntities.push(log.topics[1]);
|
|
432
|
-
else if (index < totalCreates + totalDeletes) deletedEntities.push(log.topics[1]);
|
|
433
|
-
else if (index < totalCreates + totalUpdates + totalDeletes) updatedEntities.push(log.topics[1]);
|
|
434
|
-
else if (index < totalCreates + totalUpdates + totalDeletes + totalExtensions) extendedEntities.push(log.topics[1]);
|
|
435
|
-
else ownershipChanges.push(log.topics[1]);
|
|
436
|
-
}
|
|
437
|
-
return {
|
|
438
|
-
createdEntities,
|
|
439
|
-
updatedEntities,
|
|
440
|
-
deletedEntities,
|
|
441
|
-
extendedEntities,
|
|
442
|
-
ownershipChanges
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
502
|
async function mutateEntities(client, data, txParams) {
|
|
446
503
|
if (!data.creates && !data.updates && !data.deletes && !data.extensions) throw new Error("No operations to perform");
|
|
447
|
-
const receipt = await sendArkivTransaction(client,
|
|
448
|
-
creates: data.creates ?? [],
|
|
449
|
-
updates: data.updates ?? [],
|
|
450
|
-
deletes: data.deletes ?? [],
|
|
451
|
-
extensions: data.extensions ?? [],
|
|
452
|
-
ownershipChanges: data.ownershipChanges ?? []
|
|
453
|
-
}), txParams);
|
|
504
|
+
const { receipt, createdEntityKeys } = await sendArkivTransaction(client, data, txParams);
|
|
454
505
|
logger$1("Receipt from mutateEntities %o", receipt);
|
|
455
|
-
const { createdEntities, updatedEntities, deletedEntities, extendedEntities, ownershipChanges } = parseReceipt(receipt, data);
|
|
456
506
|
return {
|
|
457
507
|
txHash: receipt.transactionHash,
|
|
458
|
-
createdEntities,
|
|
459
|
-
updatedEntities,
|
|
460
|
-
deletedEntities,
|
|
461
|
-
extendedEntities,
|
|
462
|
-
ownershipChanges
|
|
508
|
+
createdEntities: createdEntityKeys,
|
|
509
|
+
updatedEntities: (data.updates ?? []).map((u) => u.entityKey),
|
|
510
|
+
deletedEntities: (data.deletes ?? []).map((d) => d.entityKey),
|
|
511
|
+
extendedEntities: (data.extensions ?? []).map((e) => e.entityKey),
|
|
512
|
+
ownershipChanges: (data.ownershipChanges ?? []).map((o) => o.entityKey)
|
|
463
513
|
};
|
|
464
514
|
}
|
|
465
515
|
|
|
@@ -468,11 +518,11 @@ async function mutateEntities(client, data, txParams) {
|
|
|
468
518
|
const logger = getLogger("actions:wallet:update-entity");
|
|
469
519
|
async function updateEntity(client, data, txParams) {
|
|
470
520
|
logger("updateEntity %o", data);
|
|
471
|
-
const receipt = await sendArkivTransaction(client,
|
|
521
|
+
const { receipt } = await sendArkivTransaction(client, { updates: [data] }, txParams);
|
|
472
522
|
logger("Receipt from updateEntity %o", receipt);
|
|
473
523
|
return {
|
|
474
524
|
txHash: receipt.transactionHash,
|
|
475
|
-
entityKey:
|
|
525
|
+
entityKey: data.entityKey
|
|
476
526
|
};
|
|
477
527
|
}
|
|
478
528
|
|
|
@@ -535,5 +585,5 @@ function chainFromName(name) {
|
|
|
535
585
|
}
|
|
536
586
|
|
|
537
587
|
//#endregion
|
|
538
|
-
export { EntityMutationError, NoCursorOrLimitError, NoEntityFoundError, NoMoreResultsError, chainFromName, createPublicClient, createWalletClient, jsonToPayload, stringToPayload };
|
|
588
|
+
export { DuplicateAttributeError, EntityMutationError, EntityOperationType, InvalidAttributeError, InvalidAttributeKeyError, InvalidContentTypeError, InvalidExpirationError, NoCursorOrLimitError, NoEntityFoundError, NoMoreResultsError, chainFromName, createPublicClient, createWalletClient, jsonToPayload, stringToPayload };
|
|
539
589
|
//# sourceMappingURL=index.js.map
|