@aeternity/aepp-sdk
Version:
SDK for the æternity blockchain
243 lines (242 loc) • 8.88 kB
TypeScript
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 {};