Skip to content

Commit

Permalink
feat: extend acc interface, use deploy estimate fee
Browse files Browse the repository at this point in the history
  • Loading branch information
tabaktoni committed Nov 24, 2022
1 parent 931e8f8 commit da7392a
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 51 deletions.
67 changes: 27 additions & 40 deletions src/account/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Abi,
Call,
DeclareContractResponse,
DeployContract2Response,
DeployContractResponse,
EstimateFeeAction,
InvocationsDetails,
Expand All @@ -19,16 +20,17 @@ import { EstimateFee, EstimateFeeDetails } from '../types/account';
import {
AllowArray,
DeclareContractPayload,
DeclareDeployContractPayload,
DeployAccountContractPayload,
UniversalDeployerContractPayload,
} from '../types/lib';
import { AccountDeployContractResponse, InvokeTransactionReceiptResponse } from '../types/provider';
import { parseUDCEvent } from '../utils/events';
import {
calculateContractAddressFromHash,
feeTransactionVersion,
transactionVersion,
} from '../utils/hash';
import { BigNumberish, cleanHex, toBN, toCairoBool } from '../utils/number';
import { BigNumberish, toBN, toCairoBool } from '../utils/number';
import { parseContract } from '../utils/provider';
import { compileCalldata, estimatedFeeToMaxFee, randomAddress } from '../utils/stark';
import { fromCallsToExecuteCalldata } from '../utils/transaction';
Expand Down Expand Up @@ -170,7 +172,7 @@ export class Account extends Provider implements AccountInterface {
public async estimateDeployFee(
{
classHash,
salt,
salt = '0',
unique = true,
constructorCalldata = [],
additionalCalls = [],
Expand Down Expand Up @@ -278,11 +280,21 @@ export class Account extends Provider implements AccountInterface {
constructorCalldata = [],
additionalCalls = [],
}: UniversalDeployerContractPayload,
transactionsDetail: InvocationsDetails = {}
{ nonce, version, maxFee }: InvocationsDetails = {}
): Promise<InvokeFunctionResponse> {
const compiledConstructorCallData = compileCalldata(constructorCalldata);
const callsArray = Array.isArray(additionalCalls) ? additionalCalls : [additionalCalls];
const randomSalt = salt ?? randomAddress();
const deploySalt = salt ?? randomAddress();

const deployMaxFee =
maxFee ??
(await this.getSuggestedMaxFee(
{
type: 'DEPLOY',
payload: { classHash, salt: deploySalt, unique, constructorCalldata, additionalCalls },
},
{}
));

return this.execute(
[
Expand All @@ -291,7 +303,7 @@ export class Account extends Provider implements AccountInterface {
entrypoint: UDC.ENTRYPOINT,
calldata: [
classHash,
randomSalt,
deploySalt,
toCairoBool(unique),
compiledConstructorCallData.length,
...compiledConstructorCallData,
Expand All @@ -300,7 +312,11 @@ export class Account extends Provider implements AccountInterface {
...callsArray,
],
undefined,
transactionsDetail
{
nonce,
maxFee: deployMaxFee,
version,
}
);
}

Expand All @@ -309,48 +325,19 @@ export class Account extends Provider implements AccountInterface {
*
* @param payload UniversalDeployerContractPayload
* @param detials InvocationsDetails
* @returns Promise<AccountDeployContractResponse | Error>
* @returns Promise<AccountDeployContractResponse>
*/
public async deployContract2(
payload: UniversalDeployerContractPayload,
details: InvocationsDetails = {}
): Promise<AccountDeployContractResponse | Error> {
): Promise<DeployContract2Response> {
const deployTx = await this.deploy(payload, details);
const txReceipt = await this.waitForTransaction(deployTx.transaction_hash);
return this.getUDCResponse(txReceipt);
}

/**
* Parse Transaction Receipt Event from UDC invoke transaction and
* create DeployContractResponse compatibile response with adition of UDC Event data
*
* @param txReceipt
* @returns DeployContractResponse | UDC Event Response data
*/
public getUDCResponse(txReceipt: InvokeTransactionReceiptResponse | void) {
if (txReceipt && txReceipt.events) {
const event = txReceipt.events.find(
(it) => cleanHex(it.from_address) === cleanHex(UDC.ADDRESS)
) || {
data: [],
};
return {
transaction_hash: txReceipt.transaction_hash,
contract_address: event.data[0],
address: event.data[0],
deployer: event.data[1],
unique: event.data[2],
classHash: event.data[3],
calldata_len: event.data[4],
calldata: event.data.slice(5, 5 + parseInt(event.data[4], 16)),
salt: event.data[event.data.length - 1],
};
}
return new Error("UDC didn't emmit event");
return parseUDCEvent(txReceipt);
}

public async declareDeploy(
{ classHash, contract, constructorCalldata }: any,
{ classHash, contract, constructorCalldata }: DeclareDeployContractPayload,
details?: InvocationsDetails
) {
const { transaction_hash } = await this.declare({ contract, classHash }, details);
Expand Down
30 changes: 26 additions & 4 deletions src/account/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Abi,
Call,
DeclareContractResponse,
DeclareDeployContractResponse,
DeployContractResponse,
EstimateFeeAction,
EstimateFeeDetails,
Expand All @@ -16,6 +17,7 @@ import {
import {
AllowArray,
DeclareContractPayload,
DeclareDeployContractPayload,
DeployAccountContractPayload,
UniversalDeployerContractPayload,
} from '../types/lib';
Expand Down Expand Up @@ -148,10 +150,10 @@ export abstract class AccountInterface extends ProviderInterface {
*
* @param deployContractPayload containing
* - classHash: computed class hash of compiled contract
* - salt: address salt
* - unique: bool if true ensure unique salt
* - calldata: constructor calldata
* - additionalCalls - optional additional calls array to support multicall
* - constructorCalldata: constructor calldata
* - optional salt: address salt - default random
* - optional unique: bool if true ensure unique salt - default true
* - optional additionalCalls - optional additional calls array to support multicall
* @param transactionsDetail Invocation Details containing:
* - optional nonce
* - optional version
Expand All @@ -162,6 +164,26 @@ export abstract class AccountInterface extends ProviderInterface {
transactionsDetail?: InvocationsDetails
): Promise<InvokeFunctionResponse>;

/**
* Declares and Deploy a given compiled contract (json) to starknet using UDC
*
* @param declareDeployerContractPayload containing
* - contract: compiled contract code
* - classHash: computed class hash of compiled contract
* - optional constructorCalldata: constructor calldata
* - optional salt: address salt - default random
* - optional unique: bool if true ensure unique salt - default true
* - optional additionalCalls: - optional additional calls array to support multicall
* @param details
* - optional nonce
* - optional version
* - optional maxFee
*/
public abstract declareDeploy(
declareDeployerContractPayload: DeclareDeployContractPayload,
details?: InvocationsDetails
): Promise<DeclareDeployContractResponse | Error>;

/**
* Deploy the account on Starknet
*
Expand Down
22 changes: 21 additions & 1 deletion src/types/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import BN from 'bn.js';

import { BlockIdentifier } from '../provider/utils';
import { BigNumberish } from '../utils/number';
import { EstimateFeeResponse } from './provider';
import { DeclareTransactionReceiptResponse, EstimateFeeResponse } from './provider';

export interface EstimateFee extends EstimateFeeResponse {
suggestedMaxFee: BN;
Expand All @@ -12,3 +12,23 @@ export interface EstimateFeeDetails {
nonce?: BigNumberish;
blockIdentifier?: BlockIdentifier;
}

export interface DeployContractResponse {
contract_address: string;
transaction_hash: string;
}

export interface DeployContract2Response extends DeployContractResponse {
address: string;
deployer: string;
unique: string;
classHash: string;
calldata_len: string;
calldata: Array<string>;
salt: string;
}

export type DeclareDeployContractResponse = {
declare: DeclareTransactionReceiptResponse;
deploy: DeployContract2Response;
};
9 changes: 3 additions & 6 deletions src/types/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ export type UniversalDeployerContractPayload = {
additionalCalls?: AllowArray<Call>; // support multicall
};

export type DeployContractPayload = {
contract: CompiledContract | string;
constructorCalldata?: RawCalldata;
addressSalt?: string;
};

export type DeployAccountContractPayload = {
classHash: BigNumberish;
constructorCalldata?: RawCalldata;
Expand All @@ -52,6 +46,9 @@ export type DeclareContractPayload = {
classHash: BigNumberish; // Once the classHash is included in CompiledContract, this can be removed
};

export type DeclareDeployContractPayload = DeclareContractPayload &
UniversalDeployerContractPayload;

export type DeclareContractTransaction = {
contractDefinition: ContractClass;
senderAddress: string;
Expand Down
32 changes: 32 additions & 0 deletions src/utils/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { UDC } from '../constants';
import { InvokeTransactionReceiptResponse } from '../types/provider';
import { cleanHex } from './number';

/**
* Parse Transaction Receipt Event from UDC invoke transaction and
* create DeployContractResponse compatibile response with adition of UDC Event data
*
* @param txReceipt
* @returns DeployContractResponse | UDC Event Response data
*/
export function parseUDCEvent(txReceipt: InvokeTransactionReceiptResponse) {
if (!txReceipt.events) {
throw new Error('UDC emited event is empty');
}
const event = txReceipt.events.find(
(it) => cleanHex(it.from_address) === cleanHex(UDC.ADDRESS)
) || {
data: [],
};
return {
transaction_hash: txReceipt.transaction_hash,
contract_address: event.data[0],
address: event.data[0],
deployer: event.data[1],
unique: event.data[2],
classHash: event.data[3],
calldata_len: event.data[4],
calldata: event.data.slice(5, 5 + parseInt(event.data[4], 16)),
salt: event.data[event.data.length - 1],
};
}

0 comments on commit da7392a

Please sign in to comment.