UNPKG

@arkiv-network/sdk

Version:

TypeScript client library for Arkiv's blockchains interactions

110 lines (101 loc) • 3.83 kB
import type { Hash, Hex } from "viem" import type { ArkivClient } from "../../clients/baseClient" import type { CreationFlags, Expiry, NO_SALT, SaltInput } from "../../entity" import { EntityMutationError } from "../../errors" import type { CreateEntityValues, Schema } from "../../schema" import type { TxParams } from "../../types" import { sendArkivTransaction } from "../../utils/arkivTransactions" import type { ExpirationTime } from "../../utils/expirationTime" import { getLogger } from "../../utils/logger" const logger = getLogger("actions:wallet:create-entity") /** * How an created entity lives: its lifetime, plus the flags and salt it is created with. * * @example * { expiration: ExpirationTime.fromDays(30) } * * @example Pin an absolute deadline, but never let it leave the entity with less than a day: * { * expiration: ExpirationTime.atDate(someDeadline, { * atLeast: ExpirationTime.fromDays(1), // ...but live at least a day regardless * }), * flags: { readonly: true }, * } */ export type CreateEntityOptions = { /** * How long the entity should live, built with {@link ExpirationTime}. * * `ExpirationTime.fromDays(30)` is the everyday form. `atBlock` / `atDate` pin an absolute * deadline instead, and either can carry `{ atLeast }` to guarantee a minimum life on top of it. */ expiration: Expiry /** * Properties fixed at creation: `readonly` and `permissionlessExtension`. No operation changes * them afterwards, so an entity is whatever it was created as for life. Both default to `false`. */ flags?: CreationFlags | undefined /** * The salt mixed into the entity key. Defaults to 128 random bits, which makes the key * unpredictable to everyone but the creator. * * Pass {@link NO_SALT} for a key derived from the owner and nonce alone — predictable by anyone, * which is what you want only when a third party must be able to compute the key in advance. */ salt?: SaltInput | undefined } /** * One entity to create, as a batch carries it: the schema, the values, and the {@link CreateEntityOptions}. * * @typeParam S - The schema the values are typed by. */ export type CreateEntityParameters<S extends Schema = Schema> = CreateEntityOptions & { /** The schema the entity is written through. */ schema: S /** * The entity's values, keyed by column. Every required column must be given; an optional one may * be left out, and a defaulted one left out is written with its default. */ values: CreateEntityValues<S> } /** * The result of creating an entity. */ export type CreateEntityReturnType = { /** The new entity's key. */ entityKey: Hex txHash: Hash /** * The block the entity expires at, as the engine recorded it — read from the `EntityCreated` * event, so a duration is already resolved against the block the transaction landed in. */ expiresAt: bigint } export async function createEntity<S extends Schema>( client: ArkivClient, schema: S, values: CreateEntityValues<S>, options: CreateEntityOptions, txParams?: TxParams, ): Promise<CreateEntityReturnType> { logger("createEntity %o", values) const { receipt, createdEntityKeys, createdExpiries } = await sendArkivTransaction( client, { creates: [{ ...options, schema, values }] }, txParams, ) logger("Receipt from createEntity %o", receipt) const [entityKey] = createdEntityKeys const [expiresAt] = createdExpiries if (entityKey === undefined || expiresAt === undefined) { throw new EntityMutationError( `Transaction ${receipt.transactionHash} succeeded, but the receipt did not carry the expected entity key or expiry.`, { txHash: receipt.transactionHash }, ) } return { txHash: receipt.transactionHash as Hash, entityKey, expiresAt, } }