UNPKG

@aeternity/aepp-sdk

Version:

SDK for the æternity blockchain

243 lines (242 loc) 8.88 kB
import BigNumber from 'bignumber.js'; import { AbiVersion, VmVersion } from '../tx/builder/constants.js'; import { SignTx, ChannelState, ChannelOptions } from './internal.js'; import { Encoded } from '../utils/encoder.js'; import { ContractCallObjectReturnType } from '../apis/node/index.js'; import { ContractCallObject } from '../contract/Contract.js'; import ChannelSpend from './Spend.js'; interface CallContractOptions { /** * Amount the caller of the contract commits to it */ amount?: number | BigNumber; /** * ABI encoded compiled AEVM call data for the code */ callData?: Encoded.ContractBytearray; /** * Version of the ABI */ abiVersion?: AbiVersion; /** * Address of the contract to call */ contract?: Encoded.ContractAddress; } interface CallContractResult extends CallContractOptions { returnValue?: any; gasUsed?: number | BigNumber; gasPrice?: number | BigNumber; height?: number; callerNonce?: number; log?: any; returnType?: ContractCallObjectReturnType; } interface Contract { abiVersion: AbiVersion; active: boolean; deposit: number | BigNumber; id: string; ownerId: string; referrerIds: string[]; vmVersion: VmVersion; } /** * @category state channel */ export default class ChannelContract extends ChannelSpend { static initialize(options: ChannelOptions): Promise<ChannelContract>; /** * Trigger create contract update * * The create contract update is creating a contract inside the channel's internal state tree. * The update is a change to be applied on top of the latest state. * * That would create a contract with the poster being the owner of it. Poster commits initially * a deposit amount of coins to the new contract. * * @param options - Options * @param options.code - Api encoded compiled AEVM byte code * @param options.callData - Api encoded compiled AEVM call data for the code * @param options.deposit - Initial amount the owner of the contract commits to it * @param options.vmVersion - Version of the Virtual Machine * @param options.abiVersion - Version of the Application Binary Interface * @param sign - Function which verifies and signs create contract transaction * @example * ```js * channel.createContract({ * code: 'cb_HKtpipK4aCgYb17wZ...', * callData: 'cb_1111111111111111...', * deposit: 10, * vmVersion: 3, * abiVersion: 1 * }).then(({ accepted, signedTx, address }) => { * if (accepted) { * console.log('New contract has been created') * console.log('Contract address:', address) * } else { * console.log('New contract has been rejected') * } * }) * ``` */ createContract({ code, callData, deposit, vmVersion, abiVersion, }: { code: Encoded.ContractBytearray; callData: Encoded.ContractBytearray; deposit: number | BigNumber; vmVersion: VmVersion; abiVersion: AbiVersion; }, sign: SignTx): Promise<{ accepted: boolean; signedTx: Encoded.Transaction; address: Encoded.ContractAddress; }>; /** * Trigger call a contract update * * The call contract update is calling a preexisting contract inside the channel's * internal state tree. The update is a change to be applied on top of the latest state. * * That would call a contract with the poster being the caller of it. Poster commits * an amount of coins to the contract. * * The call would also create a call object inside the channel state tree. It contains * the result of the contract call. * * It is worth mentioning that the gas is not consumed, because this is an off-chain * contract call. It would be consumed if it were an on-chain one. This could happen * if a call with a similar computation amount is to be forced on-chain. * * @param options - Options * @param sign - Function which verifies and signs contract call transaction * @example * ```js * channel.callContract({ * contract: 'ct_9sRA9AVE4BYTAkh5RNfJYmwQe1NZ4MErasQLXZkFWG43TPBqa', * callData: 'cb_1111111111111111...', * amount: 0, * abiVersion: 1 * }).then(({ accepted, signedTx }) => { * if (accepted) { * console.log('Contract called succesfully') * } else { * console.log('Contract call has been rejected') * } * }) * ``` */ callContract({ amount, callData, contract, abiVersion }: CallContractOptions, sign: SignTx): Promise<{ accepted: boolean; signedTx: Encoded.Transaction; }>; /** * Trigger a force progress contract call * This call is going on-chain * @param options - Options * @param sign - Function which verifies and signs contract force progress transaction * @param callbacks - Callbacks * @example * ```js * channel.forceProgress({ * contract: 'ct_9sRA9AVE4BYTAkh5RNfJYmwQe1NZ4MErasQLXZkFWG43TPBqa', * callData: 'cb_1111111111111111...', * amount: 0, * abiVersion: 1, * gasPrice: 1000005554 * }).then(({ accepted, signedTx }) => { * if (accepted) { * console.log('Contract force progress call successful') * } else { * console.log('Contract force progress call has been rejected') * } * }) * ``` */ forceProgress({ amount, callData, contract, abiVersion, gasLimit, gasPrice, }: CallContractOptions & { gasLimit?: number; gasPrice?: number; }, sign: SignTx, { onOnChainTx }?: Pick<ChannelState, 'onOnChainTx'>): Promise<{ accepted: boolean; signedTx: Encoded.Transaction; tx: Encoded.Transaction | Uint8Array; }>; /** * Call contract using dry-run * * In order to get the result of a potential contract call, one might need to * dry-run a contract call. It takes the exact same arguments as a call would * and returns the call object. * * The call is executed in the channel's state, but it does not impact the state * whatsoever. It uses as an environment the latest channel's state and the current * top of the blockchain as seen by the node. * * @param options - Options * @example * ```js * channel.callContractStatic({ * contract: 'ct_9sRA9AVE4BYTAkh5RNfJYmwQe1NZ4MErasQLXZkFWG43TPBqa', * callData: 'cb_1111111111111111...', * amount: 0, * abiVersion: 1 * }).then(({ returnValue, gasUsed }) => { * console.log('Returned value:', returnValue) * console.log('Gas used:', gasUsed) * }) * ``` */ callContractStatic({ amount, callData, contract, abiVersion, }: CallContractOptions): Promise<CallContractResult>; /** * Get contract call result * * The combination of a caller, contract and a round of execution determines the * contract call. Providing an incorrect set of those results in an error response. * * @param options - Options * @param options.caller - Address of contract caller * @param options.contract - Address of the contract * @param options.round - Round when contract was called * @example * ```js * channel.getContractCall({ * caller: 'ak_Y1NRjHuoc3CGMYMvCmdHSBpJsMDR6Ra2t5zjhRcbtMeXXLpLH', * contract: 'ct_9sRA9AVE4BYTAkh5RNfJYmwQe1NZ4MErasQLXZkFWG43TPBqa', * round: 3 * }).then(({ returnType, returnValue }) => { * if (returnType === 'ok') console.log(returnValue) * }) * ``` */ getContractCall({ caller, contract, round, }: { caller: Encoded.AccountAddress; contract: Encoded.ContractAddress; round: number; }): Promise<ContractCallObject>; /** * Get the latest contract state * * @param contract - Address of the contract * @example * ```js * channel.getContractState( * 'ct_9sRA9AVE4BYTAkh5RNfJYmwQe1NZ4MErasQLXZkFWG43TPBqa' * ).then(({ contract }) => { * console.log('deposit:', contract.deposit) * }) * ``` */ getContractState(contract: Encoded.ContractAddress): Promise<{ contract: Contract; contractState: object; }>; /** * Clean up all locally stored contract calls * * Contract calls are kept locally in order for the participant to be able to look them up. * They consume memory and in order for the participant to free it - one can prune all messages. * This cleans up all locally stored contract calls and those will no longer be available for * fetching and inspection. */ cleanContractCalls(): Promise<void>; } export {};