@arkiv-network/sdk 0.8.0-advanced.2 → 0.8.0-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -42
- package/dist/attr/index.cjs +33 -34
- package/dist/attr/index.d.cts +1 -1
- package/dist/attr/index.d.ts +1 -2
- package/dist/attr/index.js +1 -2
- package/dist/{attributes-Df9IsCVs.cjs → attr-BXTkpnoc.cjs} +13 -3
- package/dist/{attributes-BhY5DwJp.js → attr-tmyREHtw.js} +14 -4
- package/dist/attr-tmyREHtw.js.map +1 -0
- package/dist/chains/index.cjs +1 -1
- package/dist/chains/index.d.cts +3 -0
- package/dist/chains/index.d.cts.map +1 -1
- package/dist/chains/index.d.ts +3 -0
- package/dist/chains/index.d.ts.map +1 -1
- package/dist/chains/index.js +1 -1
- package/dist/{chains-BYRTTipa.cjs → chains-BfNQliHU.cjs} +3 -0
- package/dist/{chains-BJrZs6sG.js → chains-Du8tql7I.js} +4 -1
- package/dist/chains-Du8tql7I.js.map +1 -0
- package/dist/{arkivTransactions-NtGD6uk5.d.ts → changeOwnership-B0ar96ub.d.ts} +74 -123
- package/dist/changeOwnership-B0ar96ub.d.ts.map +1 -0
- package/dist/{arkivTransactions-D74gERHG.d.cts → changeOwnership-BofkLnXJ.d.cts} +74 -123
- package/dist/changeOwnership-BofkLnXJ.d.cts.map +1 -0
- package/dist/entity/index.cjs +9 -9
- package/dist/entity/index.d.cts +3 -3
- package/dist/entity/index.d.ts +4 -5
- package/dist/entity/index.js +5 -6
- package/dist/{entity-BYQR1uoe.js → entity-BIp_df9u.js} +1 -1
- package/dist/{entity-BYQR1uoe.js.map → entity-BIp_df9u.js.map} +1 -1
- package/dist/{key-D1Bh7MF0.js → entity-CniBgBSd.js} +31 -19
- package/dist/entity-CniBgBSd.js.map +1 -0
- package/dist/{key-WKhXnXuU.cjs → entity-DJ0Gml9c.cjs} +37 -19
- package/dist/{errors-LTe7bOYS.js → errors-D2E1GRjw.js} +2 -2
- package/dist/errors-D2E1GRjw.js.map +1 -0
- package/dist/{errors-BVbjKVMN.cjs → errors-DhV00966.cjs} +1 -1
- package/dist/{expiry-nDbCgZX4.d.ts → expiry-BxOlvVWC.d.ts} +1 -1
- package/dist/{expiry-nDbCgZX4.d.ts.map → expiry-BxOlvVWC.d.ts.map} +1 -1
- package/dist/{expiry-BELY2Kpw.cjs → expiry-CG9GhVXv.cjs} +1 -1
- package/dist/{expiry-BjpxZZQU.js → expiry-Cgdb_dbq.js} +2 -2
- package/dist/expiry-Cgdb_dbq.js.map +1 -0
- package/dist/expiry-DRV29F1r.d.cts.map +1 -1
- package/dist/{flags-CRjPpoh3.d.cts → flags-0Vl5rrHq.d.cts} +1 -1
- package/dist/{flags-CRjPpoh3.d.cts.map → flags-0Vl5rrHq.d.cts.map} +1 -1
- package/dist/{flags-kr276q6i.cjs → flags-DCD26uhe.cjs} +1 -1
- package/dist/{flags-DFBs2J94.js → flags-DUT2gHEU.js} +2 -2
- package/dist/{flags-DFBs2J94.js.map → flags-DUT2gHEU.js.map} +1 -1
- package/dist/{flags-5dTNRnow.d.ts → flags-wmcMoAnN.d.ts} +1 -1
- package/dist/{flags-5dTNRnow.d.ts.map → flags-wmcMoAnN.d.ts.map} +1 -1
- package/dist/{index-fX_XyqLp.d.ts → index-BGp2plHs.d.cts} +15 -13
- package/dist/index-BGp2plHs.d.cts.map +1 -0
- package/dist/{index-DHDud2hC.d.ts → index-BKB875Um.d.ts} +5 -7
- package/dist/{index-DHDud2hC.d.ts.map → index-BKB875Um.d.ts.map} +1 -1
- package/dist/{index-DvYvrkdk.d.ts → index-CIcHPx2j.d.cts} +110 -6
- package/dist/index-CIcHPx2j.d.cts.map +1 -0
- package/dist/{index-CV5zCdpa.d.cts → index-Cd2aaWme.d.ts} +13 -6
- package/dist/index-Cd2aaWme.d.ts.map +1 -0
- package/dist/{index-CA4V7Pdh.d.cts → index-ezMZ2-JH.d.ts} +15 -13
- package/dist/index-ezMZ2-JH.d.ts.map +1 -0
- package/dist/{index-BF7Mq9Is.d.cts → index-rINthNuU.d.cts} +5 -7
- package/dist/{index-BF7Mq9Is.d.cts.map → index-rINthNuU.d.cts.map} +1 -1
- package/dist/index.cjs +433 -139
- package/dist/index.d.cts +58 -164
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +59 -166
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +376 -75
- package/dist/index.js.map +1 -1
- package/dist/{payload-CcUj85ys.d.ts → payload-CGvVPZQX.d.ts} +61 -2
- package/dist/payload-CGvVPZQX.d.ts.map +1 -0
- package/dist/{payload-Bz6651ax.js → payload-DE7wMztL.js} +28 -3
- package/dist/payload-DE7wMztL.js.map +1 -0
- package/dist/{payload-BNoud2KZ.d.cts → payload-Dfu30njp.d.cts} +60 -1
- package/dist/payload-Dfu30njp.d.cts.map +1 -0
- package/dist/{payload-KC14SDlN.cjs → payload-DqFweqiO.cjs} +27 -2
- package/dist/query/index.cjs +5 -7
- package/dist/query/index.d.cts +4 -4
- package/dist/query/index.d.ts +4 -5
- package/dist/query/index.js +5 -7
- package/dist/{queryBuilder-DM6AWCBa.js → queryBuilder-wvA8sn--.js} +169 -23
- package/dist/queryBuilder-wvA8sn--.js.map +1 -0
- package/dist/{queryBuilder-DbUMEZln.cjs → queryBuilder-zHGhDmaG.cjs} +215 -33
- package/dist/{selection-DPg0uyJf.d.cts → selection-Bv8_o-7i.d.cts} +76 -68
- package/dist/selection-Bv8_o-7i.d.cts.map +1 -0
- package/dist/{selection-C4UhsMOO.d.ts → selection-ox7zdtVm.d.ts} +76 -69
- package/dist/selection-ox7zdtVm.d.ts.map +1 -0
- package/dist/types/index.cjs +2 -2
- package/dist/types/index.d.cts +6 -6
- package/dist/types/index.d.ts +7 -8
- package/dist/types/index.js +2 -2
- package/dist/utils/index.cjs +3 -3
- package/dist/utils/index.d.cts +1 -1
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.js +3 -3
- package/package.json +1 -5
- package/src/actions/public/getEntity.ts +1 -0
- package/src/actions/public/predictEntityKeys.test.ts +17 -1
- package/src/actions/public/predictEntityKeys.ts +28 -14
- package/src/actions/public/query.ts +1 -5
- package/src/actions/wallet/createEntity.ts +7 -6
- package/src/actions/wallet/{mutateEntities.test.ts → executeBatch.test.ts} +7 -7
- package/src/actions/wallet/{mutateEntities.ts → executeBatch.ts} +26 -11
- package/src/actions/wallet/extendEntity.ts +1 -0
- package/src/actions/wallet/patchEntity.ts +3 -3
- package/src/attr/attributes.ts +8 -2
- package/src/attr/errors.ts +2 -2
- package/src/attr/types.ts +3 -3
- package/src/attr/values.ts +5 -1
- package/src/chains/localhost.ts +3 -0
- package/src/clients/createPublicClient.test.ts +1 -1
- package/src/clients/createPublicClient.ts +5 -5
- package/src/clients/createWalletClient.test.ts +2 -2
- package/src/clients/createWalletClient.ts +3 -5
- package/src/clients/decorators/arkivPublic.ts +13 -24
- package/src/clients/decorators/arkivWallet.ts +40 -47
- package/src/entity/create.test.ts +20 -1
- package/src/entity/errors.ts +4 -3
- package/src/entity/expiry.ts +1 -0
- package/src/entity/index.ts +2 -2
- package/src/entity/key.ts +23 -3
- package/src/entity/operations.ts +1 -0
- package/src/index.ts +0 -13
- package/src/query/engine.ts +0 -11
- package/src/query/errors.ts +1 -1
- package/src/query/expression.ts +14 -7
- package/src/query/queryBuilder.test.ts +1 -21
- package/src/query/queryBuilder.ts +3 -10
- package/src/types/index.ts +4 -4
- package/src/types/rpcSchema.ts +1 -0
- package/src/types/txParams.ts +8 -0
- package/src/utils/arkivTransactions.test.ts +7 -1
- package/src/utils/arkivTransactions.ts +114 -254
- package/src/utils/expirationTime.ts +39 -0
- package/src/utils/payload.ts +25 -0
- package/dist/actions/advanced/index.cjs +0 -13
- package/dist/actions/advanced/index.d.cts +0 -8
- package/dist/actions/advanced/index.d.ts +0 -9
- package/dist/actions/advanced/index.js +0 -9
- package/dist/advanced-8ZPTmmaN.js +0 -598
- package/dist/advanced-8ZPTmmaN.js.map +0 -1
- package/dist/advanced-fPImL6lW.cjs +0 -656
- package/dist/arkivTransactions-D74gERHG.d.cts.map +0 -1
- package/dist/arkivTransactions-NtGD6uk5.d.ts.map +0 -1
- package/dist/attributes-BhY5DwJp.js.map +0 -1
- package/dist/chains-BJrZs6sG.js.map +0 -1
- package/dist/codec-Car3KkFF.d.ts +0 -102
- package/dist/codec-Car3KkFF.d.ts.map +0 -1
- package/dist/entity-B7G8q_Eo.cjs +0 -0
- package/dist/entity-CD_qFF2M.js +0 -0
- package/dist/errors-LTe7bOYS.js.map +0 -1
- package/dist/expiry-BjpxZZQU.js.map +0 -1
- package/dist/index-B5j76711.d.ts +0 -184
- package/dist/index-B5j76711.d.ts.map +0 -1
- package/dist/index-CA4V7Pdh.d.cts.map +0 -1
- package/dist/index-CV5zCdpa.d.cts.map +0 -1
- package/dist/index-DvYvrkdk.d.ts.map +0 -1
- package/dist/index-EeUO0nnJ.d.cts +0 -184
- package/dist/index-EeUO0nnJ.d.cts.map +0 -1
- package/dist/index-fX_XyqLp.d.ts.map +0 -1
- package/dist/key-D1Bh7MF0.js.map +0 -1
- package/dist/logger-CVpvU8ik.js +0 -153
- package/dist/logger-CVpvU8ik.js.map +0 -1
- package/dist/logger-Cr15lPAQ.cjs +0 -188
- package/dist/payload-BNoud2KZ.d.cts.map +0 -1
- package/dist/payload-Bz6651ax.js.map +0 -1
- package/dist/payload-CcUj85ys.d.ts.map +0 -1
- package/dist/queryBuilder-DM6AWCBa.js.map +0 -1
- package/dist/selection-C4UhsMOO.d.ts.map +0 -1
- package/dist/selection-DPg0uyJf.d.cts.map +0 -1
- package/dist/types-Bu_ZwMbZ.js +0 -0
- package/dist/types-NRqymi6S.cjs +0 -0
- package/src/actions/advanced/advanced.test.ts +0 -258
- package/src/actions/advanced/buildMutation.ts +0 -104
- package/src/actions/advanced/getMutationResult.ts +0 -112
- package/src/actions/advanced/index.ts +0 -21
- package/src/actions/advanced/pingTransaction.ts +0 -43
- package/src/actions/advanced/sendMutation.ts +0 -59
- package/src/clients/decorators/arkivAdvanced.ts +0 -144
- /package/dist/{entity-B00Li04j.cjs → entity-B0t6sN7F.cjs} +0 -0
- /package/dist/{attr-DlmErkvR.cjs → types-Bx1EKe0v.js} +0 -0
- /package/dist/{attr-GcQKatub.js → types-CKPddlfS.cjs} +0 -0
|
@@ -1,598 +0,0 @@
|
|
|
1
|
-
import { a as OperationType, n as resolveExpiry, o as ARKIV_ADDRESS } from "./expiry-BjpxZZQU.js";
|
|
2
|
-
import { i as encodeMutations, r as encodeAttributes } from "./attributes-BhY5DwJp.js";
|
|
3
|
-
import { a as ENTITY_EVENTS_ABI, i as validateSalt, r as randomSalt } from "./key-D1Bh7MF0.js";
|
|
4
|
-
import { n as encodeCreationFlags } from "./flags-DFBs2J94.js";
|
|
5
|
-
import { i as InvalidContentTypeError, n as EmptyPatchError, r as EntityMutationError, t as getLogger } from "./logger-CVpvU8ik.js";
|
|
6
|
-
import { BaseError, ContractFunctionExecutionError, ContractFunctionRevertedError, TransactionExecutionError, TransactionReceiptNotFoundError, decodeEventLog, encodeAbiParameters, encodeFunctionData, hexToString, parseAbi, parseAbiParameters } from "viem";
|
|
7
|
-
|
|
8
|
-
//#region src/entity/operations.ts
|
|
9
|
-
/**
|
|
10
|
-
* The one external entry point. A transaction is an ordered, **atomic** batch of entity operations:
|
|
11
|
-
* all of them apply or none do, operation *n+1* observes operation *n*'s effects, and each applied
|
|
12
|
-
* operation emits one event.
|
|
13
|
-
*/
|
|
14
|
-
const EXECUTE_ABI = parseAbi(["function execute((uint8 operation, bytes operationData)[] ops) external returns (bytes32[] keys)"]);
|
|
15
|
-
/**
|
|
16
|
-
* The engine's one read-only view: an owner's entity-minting nonce, which is the input
|
|
17
|
-
* {@link predictEntityKey} needs and the only part of the derivation the caller cannot know.
|
|
18
|
-
*
|
|
19
|
-
* It is a `view` on the same address `execute` is called on, so it answers over `eth_call` without
|
|
20
|
-
* a transaction.
|
|
21
|
-
*/
|
|
22
|
-
const ENTITY_NONCE_ABI = parseAbi(["function entityNonce(address owner) external view returns (uint64)"]);
|
|
23
|
-
/**
|
|
24
|
-
* The shared attribute shape, used by `create` (attributes) and `patch` (mutations). Written out
|
|
25
|
-
* once and reused by every payload that carries attributes.
|
|
26
|
-
*/
|
|
27
|
-
const ATTRIBUTE_TUPLE = "(bytes32 name, uint8 typeId, bytes value)[]";
|
|
28
|
-
/**
|
|
29
|
-
* The payload struct for each operation tag. `operationData` is `abi.encode` of the struct the tag
|
|
30
|
-
* selects — a tagged union, so a new operation is additive rather than a change to `execute`.
|
|
31
|
-
*/
|
|
32
|
-
const PAYLOAD_PARAMS = {
|
|
33
|
-
[OperationType.Create]: parseAbiParameters(`(uint128 salt, uint64 expiresAt, uint64 minLifetime, uint8 creationFlags, ${ATTRIBUTE_TUPLE} attributes)`),
|
|
34
|
-
[OperationType.Patch]: parseAbiParameters(`(bytes32 entityKey, ${ATTRIBUTE_TUPLE} mutations)`),
|
|
35
|
-
[OperationType.ExtendExpiry]: parseAbiParameters("(bytes32 entityKey, uint64 expiresAt, uint64 minLifetime)"),
|
|
36
|
-
[OperationType.TransferOwnership]: parseAbiParameters("(bytes32 entityKey, address newOwner)"),
|
|
37
|
-
[OperationType.Delete]: parseAbiParameters("(bytes32 entityKey)")
|
|
38
|
-
};
|
|
39
|
-
/** Creates an entity. The key is derived by the engine; predict it with `predictEntityKey`. */
|
|
40
|
-
function createOperation({ salt, expiry, creationFlags, attributes }) {
|
|
41
|
-
return {
|
|
42
|
-
operation: OperationType.Create,
|
|
43
|
-
operationData: encodeAbiParameters(PAYLOAD_PARAMS[OperationType.Create], [{
|
|
44
|
-
salt,
|
|
45
|
-
expiresAt: expiry.expiresAt,
|
|
46
|
-
minLifetime: expiry.minLifetime,
|
|
47
|
-
creationFlags,
|
|
48
|
-
attributes
|
|
49
|
-
}])
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
/** Applies a set of mutations to an existing entity. Tombstones unset attributes. */
|
|
53
|
-
function patchOperation({ entityKey, mutations }) {
|
|
54
|
-
return {
|
|
55
|
-
operation: OperationType.Patch,
|
|
56
|
-
operationData: encodeAbiParameters(PAYLOAD_PARAMS[OperationType.Patch], [{
|
|
57
|
-
entityKey,
|
|
58
|
-
mutations
|
|
59
|
-
}])
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
/** Pushes an entity's expiry further out. Extending is allowed; shortening reverts. */
|
|
63
|
-
function extendExpiryOperation({ entityKey, expiry }) {
|
|
64
|
-
return {
|
|
65
|
-
operation: OperationType.ExtendExpiry,
|
|
66
|
-
operationData: encodeAbiParameters(PAYLOAD_PARAMS[OperationType.ExtendExpiry], [{
|
|
67
|
-
entityKey,
|
|
68
|
-
expiresAt: expiry.expiresAt,
|
|
69
|
-
minLifetime: expiry.minLifetime
|
|
70
|
-
}])
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
/** Hands an entity to a new owner. */
|
|
74
|
-
function transferOwnershipOperation({ entityKey, newOwner }) {
|
|
75
|
-
return {
|
|
76
|
-
operation: OperationType.TransferOwnership,
|
|
77
|
-
operationData: encodeAbiParameters(PAYLOAD_PARAMS[OperationType.TransferOwnership], [{
|
|
78
|
-
entityKey,
|
|
79
|
-
newOwner
|
|
80
|
-
}])
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
/** Deletes an entity before its expiry. */
|
|
84
|
-
function deleteOperation({ entityKey }) {
|
|
85
|
-
return {
|
|
86
|
-
operation: OperationType.Delete,
|
|
87
|
-
operationData: encodeAbiParameters(PAYLOAD_PARAMS[OperationType.Delete], [{ entityKey }])
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
//#endregion
|
|
92
|
-
//#region src/utils/revert.ts
|
|
93
|
-
/**
|
|
94
|
-
* Turns a decoded engine revert into a sentence that says what to change.
|
|
95
|
-
*
|
|
96
|
-
* viem decodes the error and then renders it positionally — `Ident32InvalidByte(uint256 position,
|
|
97
|
-
* bytes1 value)` arrives as `(5, 0x41)`, which is the right data and no help at all. The engine's
|
|
98
|
-
* errors carry enough to name the actual problem, so this spends the args rather than printing
|
|
99
|
-
* them.
|
|
100
|
-
*
|
|
101
|
-
* @param error - Anything thrown by a write action.
|
|
102
|
-
* @returns The explanation, or `undefined` if this was not a decodable engine revert — in which
|
|
103
|
-
* case the caller should fall back to whatever the transport said.
|
|
104
|
-
*/
|
|
105
|
-
function describeEntityRevert(error) {
|
|
106
|
-
if (!(error instanceof BaseError)) return void 0;
|
|
107
|
-
const reverted = error.walk((e) => e instanceof ContractFunctionRevertedError);
|
|
108
|
-
if (!(reverted instanceof ContractFunctionRevertedError)) return void 0;
|
|
109
|
-
const name = reverted.data?.errorName;
|
|
110
|
-
if (name === void 0) return void 0;
|
|
111
|
-
return explain(name, reverted.data?.args ?? []) ?? `the engine rejected the batch with ${name}`;
|
|
112
|
-
}
|
|
113
|
-
/** The attribute-name charset, quoted the way an error message should read. */
|
|
114
|
-
const CHARSET = "\"A\"-\"Z\", \"a\"-\"z\", \"0\"-\"9\", \".\", \"-\" and \"_\", with a letter first";
|
|
115
|
-
function explain(name, args) {
|
|
116
|
-
switch (name) {
|
|
117
|
-
case "Ident32InvalidByte": {
|
|
118
|
-
const position = Number(args[0] ?? 0);
|
|
119
|
-
return `an attribute name holds ${printable(String(args[1] ?? "0x00"))} at byte ${position}, which is outside the name charset (${CHARSET})`;
|
|
120
|
-
}
|
|
121
|
-
case "Ident32Empty": return "an attribute name is empty";
|
|
122
|
-
case "SystemAttributeNotWritable": return `"${identName(args[0])}" is owned by the engine and cannot be written. Only $payload and \$contentType are yours to set`;
|
|
123
|
-
case "TombstoneInCreate": return `a create cannot unset "${identName(args[0])}" — nothing exists yet, so leave the name out instead`;
|
|
124
|
-
case "TombstoneValueNotEmpty": return `the tombstone for "${identName(args[0])}" carries a value; unsetting takes no value`;
|
|
125
|
-
case "InvalidValueType": return `"${identName(args[0])}" names type id ${String(args[1])}, which is not a known type`;
|
|
126
|
-
case "AttributesNotSorted": return "attributes must be strictly ascending by name, which also makes each name unique";
|
|
127
|
-
case "TooManyAttributes": return `${String(args[0])} attributes exceeds the limit of ${String(args[1])}`;
|
|
128
|
-
case "EmptyMutations": return `the patch of ${short(args[0])} has no mutations, so it would do nothing`;
|
|
129
|
-
case "EntityNotFound": return `no entity ${short(args[0])} — it may have been deleted, or have expired`;
|
|
130
|
-
case "EntityExpired": return `entity ${short(args[0])} expired at block ${String(args[1])}`;
|
|
131
|
-
case "NotOwner": return `entity ${short(args[0])} is owned by ${String(args[2])}, not ${String(args[1])}`;
|
|
132
|
-
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`;
|
|
133
|
-
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`;
|
|
134
|
-
case "ExpiryDeadOnArrival": return `the expiry resolves to block ${String(args[0])}, which is not after the current block ${String(args[1])}`;
|
|
135
|
-
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`;
|
|
136
|
-
case "TransferToZeroAddress": return `entity ${short(args[0])} cannot be transferred to the zero address`;
|
|
137
|
-
case "TransferToSelf": return `entity ${short(args[0])} is already owned by that account`;
|
|
138
|
-
case "EmptyBatch": return "the batch has no operations";
|
|
139
|
-
case "InvalidOpType": return `operation tag ${String(args[0])} is not one the engine knows`;
|
|
140
|
-
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`;
|
|
141
|
-
default: return;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
/** A `bytes32` Ident32 cell as the name it holds — left-aligned, null-padded. */
|
|
145
|
-
function identName(raw) {
|
|
146
|
-
if (typeof raw !== "string") return String(raw);
|
|
147
|
-
try {
|
|
148
|
-
return hexToString(raw).split("\0")[0] ?? "";
|
|
149
|
-
} catch {
|
|
150
|
-
return raw;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
/** An entity key, abbreviated */
|
|
154
|
-
function short(raw) {
|
|
155
|
-
const text = String(raw);
|
|
156
|
-
return text.length > 18 ? `${text.slice(0, 10)}…${text.slice(-6)}` : text;
|
|
157
|
-
}
|
|
158
|
-
/** A `bytes1` as something readable: the character it is, plus the byte it was. */
|
|
159
|
-
function printable(byte) {
|
|
160
|
-
const code = Number.parseInt(byte.replace(/^0x/, ""), 16);
|
|
161
|
-
if (!Number.isFinite(code)) return `byte ${byte}`;
|
|
162
|
-
return code >= 33 && code <= 126 ? `"${String.fromCharCode(code)}" (${byte})` : `byte ${byte}`;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
//#endregion
|
|
166
|
-
//#region src/utils/arkivTransactions.ts
|
|
167
|
-
const logger$4 = getLogger("utils:arkiv-transactions");
|
|
168
|
-
const MIME_REGEX = /^[a-z][a-z0-9!#$&\-^_]*\/[a-z0-9][a-z0-9!#$&\-^_.+]*$/;
|
|
169
|
-
function validateContentType(contentType) {
|
|
170
|
-
if (!MIME_REGEX.test(contentType)) throw new InvalidContentTypeError(contentType);
|
|
171
|
-
}
|
|
172
|
-
const ENTITY_ERRORS_ABI = parseAbi([
|
|
173
|
-
"error EmptyBatch()",
|
|
174
|
-
"error InvalidOpType(uint8 operation)",
|
|
175
|
-
"error NonCanonicalOperationData(uint8 operation)",
|
|
176
|
-
"error AttributesNotSorted()",
|
|
177
|
-
"error TooManyAttributes(uint256 count, uint256 maxCount)",
|
|
178
|
-
"error EmptyMutations(bytes32 entityKey)",
|
|
179
|
-
"error TombstoneInCreate(bytes32 name)",
|
|
180
|
-
"error TombstoneValueNotEmpty(bytes32 name)",
|
|
181
|
-
"error SystemAttributeNotWritable(bytes32 name)",
|
|
182
|
-
"error InvalidValueType(bytes32 name, uint8 typeId)",
|
|
183
|
-
"error Ident32Empty()",
|
|
184
|
-
"error Ident32InvalidByte(uint256 position, bytes1 value)",
|
|
185
|
-
"error EntityNotFound(bytes32 entityKey)",
|
|
186
|
-
"error EntityExpired(bytes32 entityKey, uint64 expiresAt)",
|
|
187
|
-
"error NotOwner(bytes32 entityKey, address caller, address owner)",
|
|
188
|
-
"error ReadOnlyEntity(bytes32 entityKey)",
|
|
189
|
-
"error ReservedCreationFlags(uint8 creationFlags)",
|
|
190
|
-
"error ExpiryDeadOnArrival(uint64 target, uint64 currentBlock)",
|
|
191
|
-
"error ExpiryNotExtended(bytes32 entityKey, uint64 newExpiresAt, uint64 currentExpiresAt)",
|
|
192
|
-
"error TransferToZeroAddress(bytes32 entityKey)",
|
|
193
|
-
"error TransferToSelf(bytes32 entityKey)"
|
|
194
|
-
]);
|
|
195
|
-
const EXECUTE_ABI$1 = [...EXECUTE_ABI, ...ENTITY_ERRORS_ABI];
|
|
196
|
-
async function sendArkivTransaction(client, ops, txParams) {
|
|
197
|
-
if (!client.account) throw new Error("Account required");
|
|
198
|
-
if (!client.chain) throw new Error("Chain required");
|
|
199
|
-
const walletClient = client;
|
|
200
|
-
const { creates, extensions } = ops;
|
|
201
|
-
const operations = buildEntityOperations(ops, { currentBlock: creates?.length || extensions?.length ? await walletClient.getBlockNumber() : 0n });
|
|
202
|
-
logger$4("Sending execute with %d operations %o", operations.length, operations);
|
|
203
|
-
const txHash = await submitMutation(client, operations, txParams);
|
|
204
|
-
try {
|
|
205
|
-
const receipt = await walletClient.waitForTransactionReceipt({ hash: txHash });
|
|
206
|
-
logger$4("Tx receipt %o", receipt);
|
|
207
|
-
if (receipt.status === "reverted") {
|
|
208
|
-
try {
|
|
209
|
-
await walletClient.simulateContract({
|
|
210
|
-
address: ARKIV_ADDRESS,
|
|
211
|
-
abi: EXECUTE_ABI$1,
|
|
212
|
-
functionName: "execute",
|
|
213
|
-
args: [operations],
|
|
214
|
-
account: client.account,
|
|
215
|
-
chain: client.chain
|
|
216
|
-
});
|
|
217
|
-
} catch (err) {
|
|
218
|
-
const error = err;
|
|
219
|
-
const reason = describeEntityRevert(err) ?? error.shortMessage ?? error.cause?.details ?? "No reason provided by backend.";
|
|
220
|
-
throw new EntityMutationError(`Transaction ${receipt.transactionHash} reverted. Reason: ${reason}`);
|
|
221
|
-
}
|
|
222
|
-
throw new EntityMutationError(`Transaction ${receipt.transactionHash} reverted. No reason provided by backend.`);
|
|
223
|
-
}
|
|
224
|
-
return {
|
|
225
|
-
receipt,
|
|
226
|
-
...readAppliedOperations(receipt, {
|
|
227
|
-
creates: creates?.length ?? 0,
|
|
228
|
-
extensions: extensions?.length ?? 0
|
|
229
|
-
})
|
|
230
|
-
};
|
|
231
|
-
} catch (error) {
|
|
232
|
-
throw asEntityMutationError(error);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Wraps whatever a write step threw into an {@link EntityMutationError} — engine terms when the
|
|
237
|
-
* revert data decodes, the node's own message otherwise. An {@link EntityMutationError} passes
|
|
238
|
-
* through unchanged, so wrapped steps compose without double-wrapping.
|
|
239
|
-
*/
|
|
240
|
-
function asEntityMutationError(error) {
|
|
241
|
-
if (error instanceof EntityMutationError) return error;
|
|
242
|
-
const described = describeEntityRevert(error);
|
|
243
|
-
if (described !== void 0) return new EntityMutationError(`Transaction failed: ${described}`, { cause: error });
|
|
244
|
-
let message = "Transaction failed";
|
|
245
|
-
if (error instanceof TransactionExecutionError) message += `: ${error.details}`;
|
|
246
|
-
else if (error instanceof ContractFunctionExecutionError) {
|
|
247
|
-
logger$4("Contract function execution error data:", error.shortMessage);
|
|
248
|
-
if (error.cause instanceof ContractFunctionRevertedError) message += `: ${error.cause.message}`;
|
|
249
|
-
else message += ": Execution error without revert data";
|
|
250
|
-
} else if (error instanceof Error) message += `: ${error.message}`;
|
|
251
|
-
return new EntityMutationError(message, { cause: error });
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* The keys and expiries the engine recorded, read back from the events the batch emitted.
|
|
255
|
-
*/
|
|
256
|
-
function readAppliedOperations(receipt, expected) {
|
|
257
|
-
const events = collectMutationEvents(receipt.logs);
|
|
258
|
-
const createdEntityKeys = events.created.map((e) => e.entityKey);
|
|
259
|
-
const createdExpiries = events.created.map((e) => e.expiresAt);
|
|
260
|
-
const extendedExpiries = events.extended.map((e) => e.expiresAt);
|
|
261
|
-
assertCount(receipt, "create", createdEntityKeys.length, expected.creates);
|
|
262
|
-
assertCount(receipt, "extension", extendedExpiries.length, expected.extensions);
|
|
263
|
-
return {
|
|
264
|
-
createdEntityKeys,
|
|
265
|
-
createdExpiries,
|
|
266
|
-
extendedExpiries
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
/** One log as an entity event, or `undefined` for anything this SDK has no name for. */
|
|
270
|
-
function decodeEntityLog(log) {
|
|
271
|
-
try {
|
|
272
|
-
return decodeEventLog({
|
|
273
|
-
abi: ENTITY_EVENTS_ABI,
|
|
274
|
-
topics: log.topics,
|
|
275
|
-
data: log.data
|
|
276
|
-
});
|
|
277
|
-
} catch {
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
function assertCount(receipt, what, got, want) {
|
|
282
|
-
if (got === want) return;
|
|
283
|
-
throw new 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.`);
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Whether encoding the batch actually requires the chain head.
|
|
287
|
-
*
|
|
288
|
-
* Only a relative lifetime (`minLifetime > 0`) or a wall-clock deadline (a `Date`) is measured
|
|
289
|
-
* from the current block. A purely absolute `atBlock(n)` expiry encodes the same bytes whatever
|
|
290
|
-
* the head is, so a batch of those — or one with no expiries at all — needs no `eth_blockNumber`.
|
|
291
|
-
*/
|
|
292
|
-
function mutationNeedsBlockNumber(ops) {
|
|
293
|
-
return [...ops.creates ?? [], ...ops.extensions ?? []].some((item) => {
|
|
294
|
-
const expires = item.expires;
|
|
295
|
-
if (expires === void 0 || typeof expires.minLifetime !== "bigint") return false;
|
|
296
|
-
return expires.minLifetime !== 0n || expires.expiresAt instanceof Date;
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
/**
|
|
300
|
-
* Encodes a batch into the `execute` operations, in the order the engine applies them: creates,
|
|
301
|
-
* patches, deletes, extensions, ownership transfers.
|
|
302
|
-
*
|
|
303
|
-
* Pure — every check here is local (content types, salts, expiry bounds, non-empty patches and a
|
|
304
|
-
* non-empty batch), so the only chain input is `context.currentBlock`. Callers that carry no
|
|
305
|
-
* relative expiry (see {@link mutationNeedsBlockNumber}) can pass `0n`, which disables the
|
|
306
|
-
* dead-on-arrival pre-check and leaves that to the engine.
|
|
307
|
-
*/
|
|
308
|
-
function buildEntityOperations(ops, context) {
|
|
309
|
-
const { creates, patches, deletes, extensions, ownershipChanges } = ops;
|
|
310
|
-
const createOps = (creates ?? []).map((item) => {
|
|
311
|
-
validateContentType(item.contentType);
|
|
312
|
-
return createOperation({
|
|
313
|
-
salt: item.salt === void 0 ? randomSalt() : validateSalt(item.salt),
|
|
314
|
-
expiry: resolveExpiry(item.expires, context),
|
|
315
|
-
creationFlags: encodeCreationFlags(item.flags),
|
|
316
|
-
attributes: encodeAttributes(item.attributes, {
|
|
317
|
-
payload: item.payload,
|
|
318
|
-
contentType: item.contentType
|
|
319
|
-
})
|
|
320
|
-
});
|
|
321
|
-
});
|
|
322
|
-
const patchOps = (patches ?? []).map((item) => {
|
|
323
|
-
if (item.contentType !== void 0) validateContentType(item.contentType);
|
|
324
|
-
const mutations = encodeMutations(item);
|
|
325
|
-
if (mutations.length === 0) throw new EmptyPatchError(item.entityKey);
|
|
326
|
-
return patchOperation({
|
|
327
|
-
entityKey: item.entityKey,
|
|
328
|
-
mutations
|
|
329
|
-
});
|
|
330
|
-
});
|
|
331
|
-
const extendOps = (extensions ?? []).map((item) => {
|
|
332
|
-
const expiry = resolveExpiry(item.expires, context);
|
|
333
|
-
return extendExpiryOperation({
|
|
334
|
-
entityKey: item.entityKey,
|
|
335
|
-
expiry
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
const operations = [
|
|
339
|
-
...createOps,
|
|
340
|
-
...patchOps,
|
|
341
|
-
...(deletes ?? []).map((item) => deleteOperation({ entityKey: item.entityKey })),
|
|
342
|
-
...extendOps,
|
|
343
|
-
...(ownershipChanges ?? []).map((item) => transferOwnershipOperation({
|
|
344
|
-
entityKey: item.entityKey,
|
|
345
|
-
newOwner: item.newOwner
|
|
346
|
-
}))
|
|
347
|
-
];
|
|
348
|
-
if (operations.length === 0) throw new Error("No operations to perform");
|
|
349
|
-
return operations;
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Signs and sends an encoded batch, wrapping any node rejection in {@link EntityMutationError}.
|
|
353
|
-
*
|
|
354
|
-
* The submission half both write paths share: one `writeContract` — an `eth_sendRawTransaction`,
|
|
355
|
-
* plus only the lookups viem needs for whatever `txParams` leaves out — with no waiting and no
|
|
356
|
-
* polling. A rejection is reported in engine terms when the node returned decodable revert data,
|
|
357
|
-
* and with the node's own message otherwise; either way the caller sees an
|
|
358
|
-
* {@link EntityMutationError}.
|
|
359
|
-
*
|
|
360
|
-
* Internal seam shared with `actions/advanced/sendMutation`; not part of the package's public
|
|
361
|
-
* surface.
|
|
362
|
-
*/
|
|
363
|
-
async function submitMutation(client, operations, txParams) {
|
|
364
|
-
if (!client.account) throw new Error("Account required");
|
|
365
|
-
if (!client.chain) throw new Error("Chain required");
|
|
366
|
-
const walletClient = client;
|
|
367
|
-
try {
|
|
368
|
-
return await walletClient.writeContract({
|
|
369
|
-
address: ARKIV_ADDRESS,
|
|
370
|
-
abi: EXECUTE_ABI$1,
|
|
371
|
-
functionName: "execute",
|
|
372
|
-
args: [operations],
|
|
373
|
-
account: client.account,
|
|
374
|
-
chain: client.chain,
|
|
375
|
-
...txParams
|
|
376
|
-
});
|
|
377
|
-
} catch (error) {
|
|
378
|
-
throw asEntityMutationError(error);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
/**
|
|
382
|
-
* Reads the entity events out of a receipt's logs, exactly as they were emitted.
|
|
383
|
-
*
|
|
384
|
-
* Lenient by design: it reports what the events say and nothing else — no counting against what
|
|
385
|
-
* was asked for (the caller may not have the request at hand) and no error for a receipt with no
|
|
386
|
-
* entity events at all. Logs from other contracts and events this SDK has no name for are skipped.
|
|
387
|
-
*/
|
|
388
|
-
function collectMutationEvents(logs) {
|
|
389
|
-
const events = {
|
|
390
|
-
created: [],
|
|
391
|
-
patched: [],
|
|
392
|
-
deleted: [],
|
|
393
|
-
extended: [],
|
|
394
|
-
ownershipTransferred: []
|
|
395
|
-
};
|
|
396
|
-
for (const log of logs ?? []) {
|
|
397
|
-
if (log.address.toLowerCase() !== ARKIV_ADDRESS.toLowerCase()) continue;
|
|
398
|
-
const decoded = decodeEntityLog(log);
|
|
399
|
-
if (decoded === void 0) continue;
|
|
400
|
-
switch (decoded.eventName) {
|
|
401
|
-
case "EntityCreated":
|
|
402
|
-
events.created.push({
|
|
403
|
-
entityKey: decoded.args.entityKey,
|
|
404
|
-
owner: decoded.args.owner,
|
|
405
|
-
expiresAt: decoded.args.expiresAt
|
|
406
|
-
});
|
|
407
|
-
break;
|
|
408
|
-
case "EntityPatched":
|
|
409
|
-
events.patched.push({
|
|
410
|
-
entityKey: decoded.args.entityKey,
|
|
411
|
-
owner: decoded.args.owner
|
|
412
|
-
});
|
|
413
|
-
break;
|
|
414
|
-
case "EntityDeleted":
|
|
415
|
-
events.deleted.push({
|
|
416
|
-
entityKey: decoded.args.entityKey,
|
|
417
|
-
owner: decoded.args.owner
|
|
418
|
-
});
|
|
419
|
-
break;
|
|
420
|
-
case "ExpiryExtended":
|
|
421
|
-
events.extended.push({
|
|
422
|
-
entityKey: decoded.args.entityKey,
|
|
423
|
-
owner: decoded.args.owner,
|
|
424
|
-
expiresAt: decoded.args.expiresAt
|
|
425
|
-
});
|
|
426
|
-
break;
|
|
427
|
-
case "OwnershipTransferred":
|
|
428
|
-
events.ownershipTransferred.push({
|
|
429
|
-
entityKey: decoded.args.entityKey,
|
|
430
|
-
previousOwner: decoded.args.previousOwner,
|
|
431
|
-
newOwner: decoded.args.newOwner
|
|
432
|
-
});
|
|
433
|
-
break;
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
return events;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
//#endregion
|
|
440
|
-
//#region src/actions/advanced/buildMutation.ts
|
|
441
|
-
const logger$3 = getLogger("actions:advanced:build-mutation");
|
|
442
|
-
/**
|
|
443
|
-
* Encodes a mutation batch without sending anything.
|
|
444
|
-
*
|
|
445
|
-
* This is the first step of the advanced path: it performs only local validation and encoding, so
|
|
446
|
-
* it costs **zero RPC calls** when `options.currentBlock` is provided (or no expiry is relative),
|
|
447
|
-
* and at most one `eth_blockNumber` otherwise. Send the result however you like: pass `operations`
|
|
448
|
-
* to `writeContract`, or sign `{ to, data }` offline and push it with `eth_sendRawTransaction`.
|
|
449
|
-
*
|
|
450
|
-
* One check rides on knowing the head: an absolute `atBlock(n)` already in the past is rejected
|
|
451
|
-
* locally only when the head is supplied or was fetched anyway. With neither, a dead-on-arrival
|
|
452
|
-
* expiry encodes cleanly and the engine reverts it on-chain — see
|
|
453
|
-
* {@link BuildMutationOptions.currentBlock}.
|
|
454
|
-
*
|
|
455
|
-
* @throws {InvalidExpiryError} If an expiry exceeds a protocol bound.
|
|
456
|
-
* @throws {InvalidValueError} If an attribute value does not fit the type it names.
|
|
457
|
-
* @throws {EmptyPatchError} If a patch has nothing to apply.
|
|
458
|
-
*/
|
|
459
|
-
async function buildMutation(client, data, options = {}) {
|
|
460
|
-
const currentBlock = options.currentBlock ?? (mutationNeedsBlockNumber(data) ? await client.getBlockNumber() : 0n);
|
|
461
|
-
const operations = buildEntityOperations(data, { currentBlock });
|
|
462
|
-
logger$3("Built %d operations at block %d", operations.length, currentBlock);
|
|
463
|
-
return {
|
|
464
|
-
operations,
|
|
465
|
-
to: ARKIV_ADDRESS,
|
|
466
|
-
data: encodeFunctionData({
|
|
467
|
-
abi: EXECUTE_ABI,
|
|
468
|
-
functionName: "execute",
|
|
469
|
-
args: [operations]
|
|
470
|
-
}),
|
|
471
|
-
expected: {
|
|
472
|
-
creates: data.creates?.length ?? 0,
|
|
473
|
-
patches: data.patches?.length ?? 0,
|
|
474
|
-
deletes: data.deletes?.length ?? 0,
|
|
475
|
-
extensions: data.extensions?.length ?? 0,
|
|
476
|
-
ownershipChanges: data.ownershipChanges?.length ?? 0
|
|
477
|
-
}
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
//#endregion
|
|
482
|
-
//#region src/actions/advanced/getMutationResult.ts
|
|
483
|
-
const logger$2 = getLogger("actions:advanced:get-mutation-result");
|
|
484
|
-
/**
|
|
485
|
-
* Decodes a receipt you already hold into a {@link MutationResult}. **Zero RPC calls.**
|
|
486
|
-
*
|
|
487
|
-
* The pure tail of the advanced path: if a receipt reached you some other way — your own
|
|
488
|
-
* `waitForTransactionReceipt`, a webhook, a block watcher — this turns it into entity keys and
|
|
489
|
-
* expiries without touching the network. Lenient by design: it reports what the events say,
|
|
490
|
-
* without counting them against a request it never saw.
|
|
491
|
-
*/
|
|
492
|
-
function decodeMutationResult(receipt) {
|
|
493
|
-
const events = collectMutationEvents(receipt.logs);
|
|
494
|
-
return {
|
|
495
|
-
status: receipt.status,
|
|
496
|
-
txHash: receipt.transactionHash,
|
|
497
|
-
blockNumber: receipt.blockNumber,
|
|
498
|
-
createdEntities: events.created.map((e) => e.entityKey),
|
|
499
|
-
createdExpiries: events.created.map((e) => e.expiresAt),
|
|
500
|
-
patchedEntities: events.patched.map((e) => e.entityKey),
|
|
501
|
-
deletedEntities: events.deleted.map((e) => e.entityKey),
|
|
502
|
-
extendedEntities: events.extended.map((e) => e.entityKey),
|
|
503
|
-
extendedExpiries: events.extended.map((e) => e.expiresAt),
|
|
504
|
-
ownershipChanges: events.ownershipTransferred.map((e) => e.entityKey),
|
|
505
|
-
receipt
|
|
506
|
-
};
|
|
507
|
-
}
|
|
508
|
-
/**
|
|
509
|
-
* Fetches a transaction's receipt — once — and decodes what the mutation did.
|
|
510
|
-
*
|
|
511
|
-
* Exactly one `eth_getTransactionReceipt`, like `pingTransaction`, but the answer carries the
|
|
512
|
-
* decoded entity events as well: created keys, recorded expiries, and the keys of everything
|
|
513
|
-
* patched, deleted, extended or handed over. A transaction that is not mined yet comes back as
|
|
514
|
-
* `{ status: "pending" }` — check `status` before reading the rest.
|
|
515
|
-
*
|
|
516
|
-
* No revert diagnosis is run: a `reverted` result reports the fact and the raw receipt, and
|
|
517
|
-
* spending a `simulateContract` on the why is your call, not the SDK's.
|
|
518
|
-
*/
|
|
519
|
-
async function getMutationResult(client, txHash) {
|
|
520
|
-
const receipt = await fetchReceipt(client, txHash);
|
|
521
|
-
if (receipt === void 0) {
|
|
522
|
-
logger$2("Tx %s still pending", txHash);
|
|
523
|
-
return { status: "pending" };
|
|
524
|
-
}
|
|
525
|
-
return decodeMutationResult(receipt);
|
|
526
|
-
}
|
|
527
|
-
/**
|
|
528
|
-
* One `eth_getTransactionReceipt`, with "not there yet" as a value instead of an exception.
|
|
529
|
-
*
|
|
530
|
-
* Internal seam shared with `pingTransaction`; not part of the package's public surface.
|
|
531
|
-
*/
|
|
532
|
-
async function fetchReceipt(client, txHash) {
|
|
533
|
-
const reader = client;
|
|
534
|
-
try {
|
|
535
|
-
return await reader.getTransactionReceipt({ hash: txHash });
|
|
536
|
-
} catch (error) {
|
|
537
|
-
if (error instanceof TransactionReceiptNotFoundError) return void 0;
|
|
538
|
-
throw error;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
//#endregion
|
|
543
|
-
//#region src/actions/advanced/pingTransaction.ts
|
|
544
|
-
const logger$1 = getLogger("actions:advanced:ping-transaction");
|
|
545
|
-
/**
|
|
546
|
-
* Asks the chain — once — whether a transaction has landed.
|
|
547
|
-
*
|
|
548
|
-
* Exactly one `eth_getTransactionReceipt`, never a poll: a transaction that is not mined yet comes
|
|
549
|
-
* back as `{ status: "pending" }` rather than being waited on. This is the "ping" of the advanced
|
|
550
|
-
* path — you own the schedule, the SDK owns nothing.
|
|
551
|
-
*
|
|
552
|
-
* When it reports `success` and you need the created keys or recorded expiries, spend the next
|
|
553
|
-
* call on `getMutationResult` — or none at all, if you predicted the keys up front with
|
|
554
|
-
* `predictEntityKeys`.
|
|
555
|
-
*/
|
|
556
|
-
async function pingTransaction(client, txHash) {
|
|
557
|
-
const receipt = await fetchReceipt(client, txHash);
|
|
558
|
-
if (receipt === void 0) {
|
|
559
|
-
logger$1("Tx %s still pending", txHash);
|
|
560
|
-
return { status: "pending" };
|
|
561
|
-
}
|
|
562
|
-
return {
|
|
563
|
-
status: receipt.status,
|
|
564
|
-
blockNumber: receipt.blockNumber
|
|
565
|
-
};
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
//#endregion
|
|
569
|
-
//#region src/actions/advanced/sendMutation.ts
|
|
570
|
-
const logger = getLogger("actions:advanced:send-mutation");
|
|
571
|
-
/**
|
|
572
|
-
* Signs and sends a mutation batch, returning as soon as the transaction is submitted.
|
|
573
|
-
*
|
|
574
|
-
* The fire-and-forget half of the advanced path. Unlike `mutateEntities`, this does **not** wait
|
|
575
|
-
* for a receipt, does not poll, and runs no revert diagnosis — it spends only what submitting
|
|
576
|
-
* costs. With `options.currentBlock` and full `txParams` (nonce, gas, fees) that is exactly one
|
|
577
|
-
* RPC call; each omitted piece adds only the lookup viem needs to fill it.
|
|
578
|
-
*
|
|
579
|
-
* Follow up separately, on your own schedule:
|
|
580
|
-
* - `pingTransaction(txHash)` — one `eth_getTransactionReceipt`, tells you pending/success/reverted.
|
|
581
|
-
* - `getMutationResult(txHash)` — the same single call, plus the decoded entity keys and expiries.
|
|
582
|
-
*
|
|
583
|
-
* @throws {EntityMutationError} If the node rejects the submission (the batch never made it into
|
|
584
|
-
* the mempool) — in engine terms when the rejection decodes, with the node's message otherwise.
|
|
585
|
-
* Anything after that — inclusion, success — is yours to check.
|
|
586
|
-
*/
|
|
587
|
-
async function sendMutation(client, data, options = {}) {
|
|
588
|
-
const { operations, expected } = await buildMutation(client, data, options);
|
|
589
|
-
logger("Sending execute with %d operations (no wait)", operations.length);
|
|
590
|
-
return {
|
|
591
|
-
txHash: await submitMutation(client, operations, options.txParams),
|
|
592
|
-
expected
|
|
593
|
-
};
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
//#endregion
|
|
597
|
-
export { buildMutation as a, mutationNeedsBlockNumber as c, getMutationResult as i, sendArkivTransaction as l, pingTransaction as n, buildEntityOperations as o, decodeMutationResult as r, collectMutationEvents as s, sendMutation as t, ENTITY_NONCE_ABI as u };
|
|
598
|
-
//# sourceMappingURL=advanced-8ZPTmmaN.js.map
|