@arkiv-network/sdk
Version:
TypeScript client library for Arkiv's blockchains interactions
97 lines (93 loc) • 3.47 kB
JavaScript
import { n as ARKIV_ADDRESS } from "./consts-Lp55G1Qc.js";
import { i as NoRandomSourceError, r as InvalidSaltError } from "./errors-BLeoFbFG.js";
import { encodePacked, keccak256, parseAbi } from "viem";
//#region src/entity/params.ts
/**
* Max uint64 value
*/
const MAX_EXPIRES_AT = 2n ** 64n - 1n;
/** The operation tags of the `execute` ABI's tagged union. */
const OperationType = {
Create: 1,
Patch: 2,
ExtendExpiry: 3,
TransferOwnership: 4,
Delete: 5
};
//#endregion
//#region src/entity/key.ts
/** The widest salt the `uint128` wire field carries. */
const MAX_SALT = 2n ** 128n - 1n;
/**
* Opts a create out of salting, as {@link CreateEntityOptions.salt}: the key is then derived
* from the owner and its nonce alone, so anyone who knows both can work it out before the create
* lands.
*/
const NO_SALT = Symbol("NO_SALT");
/**
* A cryptographically random 128-bit salt — what {@link CreateEntityOptions.salt} defaults to.
*
* The salt exists for unpredictability, not uniqueness: the per-owner nonce already guarantees
* distinct keys. Random bits mean only the creator can predict the key of an entity they are about
* to create, so nobody else can reference or squat it in advance.
*
* @throws {NoRandomSourceError} If the runtime has no `crypto.getRandomValues`.
*/
function randomSalt() {
const source = globalThis.crypto;
if (typeof source?.getRandomValues !== "function") throw new NoRandomSourceError();
const bytes = source.getRandomValues(new Uint8Array(16));
let salt = 0n;
for (const byte of bytes) salt = salt << 8n | BigInt(byte);
return salt;
}
/**
* Resolves a caller-supplied salt to a `uint128`.
*/
function resolveSalt(salt) {
return salt === NO_SALT ? 0n : validateSalt(salt);
}
/** Validates a caller-supplied salt against the `uint128` wire field. */
function validateSalt(salt) {
if (typeof salt !== "bigint" || salt < 0n || salt > MAX_SALT) throw new InvalidSaltError(salt);
return salt;
}
/**
* The key an entity will be created with, derived exactly as the engine derives it:
* `keccak256(domain ++ owner ++ nonce ++ salt)`.
*
* Deriving it client-side is what lets a batch compose: predict the key of a create, then have a
* later operation in the same transaction reference it, or store it as a `key` attribute on a
* sibling entity.
*/
function predictEntityKey({ owner, nonce, salt, chainId }) {
return keccak256(encodePacked([
"uint256",
"address",
"address",
"uint64",
"uint128"
], [
BigInt(chainId),
ARKIV_ADDRESS,
owner,
nonce,
resolveSalt(salt)
]));
}
//#endregion
//#region src/entity/events.ts
/**
* The events the engine emits: one per applied operation, in application order, so an off-chain
* replica can replay a transaction operation by operation.
*/
const ENTITY_EVENTS_ABI = parseAbi([
"event EntityCreated(bytes32 indexed entityKey, address indexed owner, uint64 expiresAt, uint8 creationFlags)",
"event EntityPatched(bytes32 indexed entityKey, address indexed owner)",
"event ExpiryExtended(bytes32 indexed entityKey, address indexed owner, uint64 expiresAt)",
"event OwnershipTransferred(bytes32 indexed entityKey, address indexed previousOwner, address indexed newOwner)",
"event EntityDeleted(bytes32 indexed entityKey, address indexed owner)"
]);
//#endregion
export { randomSalt as a, OperationType as c, predictEntityKey as i, MAX_SALT as n, resolveSalt as o, NO_SALT as r, MAX_EXPIRES_AT as s, ENTITY_EVENTS_ABI as t };
//# sourceMappingURL=entity-DY0XB8so.js.map