UNPKG

@aeternity/aepp-sdk

Version:

SDK for the æternity blockchain

172 lines (171 loc) 7.24 kB
/** * Contract module - routines to interact with the æternity contract * * High level documentation of the contracts are available at * https://github.com/aeternity/protocol/tree/master/contracts and */ import { Encoder as Calldata } from '@aeternity/aepp-calldata'; import { Tag, AensName } from '../tx/builder/constants.js'; import { BuildTxOptions } from '../tx/builder/index.js'; import { Encoded } from '../utils/encoder.js'; import { ContractCallObject as NodeContractCallObject, Event as NodeEvent } from '../apis/node/index.js'; import CompilerBase, { Aci } from './compiler/Base.js'; import Node from '../Node.js'; import { txDryRun } from '../chain.js'; import { sendTransaction, SendTransactionOptions } from '../send-transaction.js'; import { TxUnpacked } from '../tx/builder/schema.generated.js'; import { Optional } from '../utils/other.js'; interface Event extends NodeEvent { address: Encoded.ContractAddress; data: Encoded.ContractBytearray; } export interface ContractCallObject extends NodeContractCallObject { returnValue: Encoded.ContractBytearray; log: Event[]; } interface DecodedEvent { name: string; args: unknown[]; contract: { name: string; address: Encoded.ContractAddress; }; } type TxData = Awaited<ReturnType<typeof sendTransaction>>; interface SendAndProcessReturnType { result?: ContractCallObject; hash: TxData['hash']; tx: TxUnpacked & { tag: Tag.SignedTx | Tag.ContractCallTx | Tag.ContractCreateTx; }; txData: TxData; rawTx: Encoded.Transaction; } /** * @category contract */ export interface ContractMethodsBase { [key: string]: (...args: any[]) => any; } type MethodsToContractApi<M extends ContractMethodsBase> = { [Name in keyof M]: M[Name] extends (...args: infer Args) => infer Ret ? (...args: [ ...Args, ...([] | [ Name extends 'init' ? Parameters<Contract<M>['$deploy']>[1] : Parameters<Contract<M>['$call']>[2] ]) ]) => Promise<Omit<Awaited<ReturnType<Contract<M>['$call']>>, 'decodedResult'> & { decodedResult: Ret; }> : never; }; /** * @category contract */ type ContractWithMethods<M extends ContractMethodsBase> = Contract<M> & MethodsToContractApi<M>; type MethodNames<M extends ContractMethodsBase> = (keyof M & string) | 'init'; type MethodParameters<M extends ContractMethodsBase, Fn extends MethodNames<M>> = Fn extends 'init' ? M extends { init: any; } ? Parameters<M['init']> : [] : Parameters<M[Fn]>; interface GetContractNameByEventOptions { contractAddressToName?: { [key: Encoded.ContractAddress]: string; }; } interface GetCallResultByHashReturnType<M extends ContractMethodsBase, Fn extends MethodNames<M>> { decodedResult: ReturnType<M[Fn]>; decodedEvents?: ReturnType<Contract<M>['$decodeEvents']>; } /** * Generate contract ACI object with predefined js methods for contract usage - can be used for * creating a reference to already deployed contracts * @category contract * @param options - Options object * @returns JS Contract API * @example * ```js * const contractIns = await Contract.initialize({ ...aeSdk.getContext(), sourceCode }) * await contractIns.$deploy([321]) or await contractIns.init(321) * const callResult = await contractIns.$call('setState', [123]) * const staticCallResult = await contractIns.$call('setState', [123], { callStatic: true }) * ``` * Also you can call contract like: `await contractIns.setState(123, options)` * Then sdk decide to make on-chain or static call (dry-run API) transaction based on function is * stateful or not */ declare class Contract<M extends ContractMethodsBase> { #private; /** * Compile contract * @returns bytecode */ $compile(): Promise<Encoded.ContractBytearray>; $getCallResultByTxHash<Fn extends MethodNames<M>>(hash: Encoded.TxHash, fnName: Fn, options?: Parameters<Contract<M>['$decodeEvents']>[1]): Promise<GetCallResultByHashReturnType<M, Fn> & { result: ContractCallObject; }>; _estimateGas<Fn extends MethodNames<M>>(name: Fn, params: MethodParameters<M, Fn>, options?: Omit<Parameters<Contract<M>['$call']>[2], 'callStatic'>): Promise<number>; /** * Deploy contract * @param params - Contract init function arguments array * @param options - Options * @returns deploy info */ $deploy(params: MethodParameters<M, 'init'>, options?: Parameters<Contract<M>['$call']>[2] & Partial<BuildTxOptions<Tag.ContractCreateTx, 'ownerId' | 'code' | 'callData'>>): Promise<Omit<SendAndProcessReturnType, 'hash'> & { transaction?: Encoded.TxHash; owner?: Encoded.AccountAddress; address?: Encoded.ContractAddress; decodedEvents?: ReturnType<Contract<M>['$decodeEvents']>; }>; /** * Call contract function * @param fn - Function name * @param params - Array of function arguments * @param options - Array of function arguments * @returns CallResult */ $call<Fn extends MethodNames<M>>(fn: Fn, params: MethodParameters<M, Fn>, options?: Partial<BuildTxOptions<Tag.ContractCallTx, 'callerId' | 'contractId' | 'callData'>> & Parameters<Contract<M>['$decodeEvents']>[1] & Optional<SendTransactionOptions, 'onAccount' | 'onNode'> & Omit<Parameters<typeof txDryRun>[2], 'onNode'> & { callStatic?: boolean; }): Promise<SendAndProcessReturnType & Partial<GetCallResultByHashReturnType<M, Fn>>>; /** * Decode Events * @param events - Array of encoded events (callRes.result.log) * @param options - Options * @returns DecodedEvents */ $decodeEvents(events: Event[], { omitUnknown, ...opt }?: { omitUnknown?: boolean; } & GetContractNameByEventOptions): DecodedEvent[]; static initialize<M extends ContractMethodsBase>({ onCompiler, onNode, bytecode, aci, address, sourceCodePath, sourceCode, fileSystem, validateBytecode, ...otherOptions }: Omit<ConstructorParameters<typeof Contract>[0], 'aci' | 'address'> & { validateBytecode?: boolean; aci?: Aci; address?: Encoded.ContractAddress | AensName; }): Promise<ContractWithMethods<M>>; _aci: Aci; _name: string; _calldata: Calldata; $options: Omit<ConstructorParameters<typeof Contract>[0], 'aci'>; /** * @param options - Options */ constructor({ aci, ...otherOptions }: { onCompiler?: CompilerBase; onNode: Node; bytecode?: Encoded.ContractBytearray; aci: Aci; address?: Encoded.ContractAddress; /** * Supported only in Ceres */ name?: AensName; sourceCodePath?: Parameters<CompilerBase['compile']>[0]; sourceCode?: Parameters<CompilerBase['compileBySourceCode']>[0]; fileSystem?: Parameters<CompilerBase['compileBySourceCode']>[1]; } & Parameters<Contract<M>['$deploy']>[1]); } interface ContractWithMethodsClass { new <M extends ContractMethodsBase>(options: ConstructorParameters<typeof Contract>[0]): ContractWithMethods<M>; initialize: (typeof Contract)['initialize']; } /** * @category contract */ declare const ContractWithMethods: ContractWithMethodsClass; export default ContractWithMethods;