diff --git a/src/types/app-client.ts b/src/types/app-client.ts
index 4fde28c8..1e4bdae6 100644
--- a/src/types/app-client.ts
+++ b/src/types/app-client.ts
@@ -61,6 +61,7 @@ import { AppSpec, arc32ToArc56 } from './app-spec'
import {
AppCallMethodCall,
AppCallParams,
+ AppCreateMethodCall,
AppDeleteMethodCall,
AppDeleteParams,
AppMethodCall,
@@ -260,9 +261,9 @@ export interface FundAppAccountParams {
/** Source maps for an Algorand app */
export interface AppSourceMaps {
/** The source map of the approval program */
- approvalSourceMap: SourceMapExport
+ approvalSourceMap: algosdk.ProgramSourceMap
/** The source map of the clear program */
- clearSourceMap: SourceMapExport
+ clearSourceMap: algosdk.ProgramSourceMap
}
export interface SourceMapExport {
@@ -353,7 +354,14 @@ export type CallOnComplete = {
/** AppClient common parameters for a bare app call */
export type AppClientBareCallParams = Expand<
- Omit<CommonAppCallParams, 'appId' | 'sender' | 'onComplete'> & {
+ Omit<CommonAppCallParams, 'appId' | 'sender'> & {
+ /** The address of the account sending the transaction, if undefined then the app client's defaultSender is used. */
+ sender?: Address | string
+ }
+>
+
+export type AppClientBareCreateParams = Expand<
+ Omit<CommonAppCallParams, 'appId' | 'sender'> & {
/** The address of the account sending the transaction, if undefined then the app client's defaultSender is used. */
sender?: Address | string
}
@@ -1193,6 +1201,15 @@ export class AppClient {
OnApplicationComplete.UpdateApplicationOC,
) as AppUpdateParams
},
+ create: async (params?: AppClientBareCallParams & AppClientCompilationParams) => {
+ return this.getBareParams(
+ {
+ ...params,
+ ...(await this.compile(params)),
+ },
+ params?.onComplete,
+ ) as AppUpdateParams
+ },
/** Return params for an opt-in call */
optIn: (params?: AppClientBareCallParams) => {
return this.getBareParams(params, OnApplicationComplete.OptInOC) as AppCallParams
@@ -1222,6 +1239,9 @@ export class AppClient {
update: async (params?: AppClientBareCallParams & AppClientCompilationParams) => {
return this._algorand.createTransaction.appUpdate(await this.params.bare.update(params))
},
+ create: async (params?: AppClientBareCallParams & AppClientCompilationParams) => {
+ return this._algorand.createTransaction.appCreate(await this.params.bare.update(params))
+ },
/** Returns a transaction for an opt-in call */
optIn: (params?: AppClientBareCallParams) => {
return this._algorand.createTransaction.appCall(this.params.bare.optIn(params))
@@ -1255,6 +1275,16 @@ export class AppClient {
...(compiled as Partial<AppCompilationResult>),
}
},
+ create: async (params?: AppClientBareCallParams & AppClientCompilationParams & SendParams) => {
+ const compiled = await this.compile(params)
+ const results = {
+ ...(await this._algorand.send.appCreate(await this.params.bare.create(params))),
+ ...(compiled as Partial<AppCompilationResult>),
+ }
+
+ this._appId = results.appId
+ return results
+ },
/** Signs and sends an opt-in call */
optIn: (params?: AppClientBareCallParams & SendParams) => {
return this._algorand.send.appCall(this.params.bare.optIn(params))
@@ -1307,6 +1337,19 @@ export class AppClient {
OnApplicationComplete.UpdateApplicationOC,
)) satisfies AppUpdateMethodCall
},
+ create: async (params: AppClientMethodCallParams & AppClientCompilationParams) => {
+ if (params.onComplete === OnApplicationComplete.ClearStateOC) {
+ throw new Error(`Cannot create with an OnComplete value of ${params.onComplete}`)
+ }
+
+ return (await this.getABIParams(
+ {
+ ...params,
+ ...(await this.compile(params)),
+ },
+ params.onComplete,
+ )) satisfies AppCreateMethodCall
+ },
/**
* Return params for an opt-in ABI call
* @param params The parameters for the opt-in ABI method call
@@ -1364,6 +1407,24 @@ export class AppClient {
...(compiled as Partial<AppCompilationResult>),
}
},
+ /**
+ * Sign and send transactions for an update ABI call, including deploy-time TEAL template replacements and compilation if provided
+ * @param params The parameters for the update ABI method call
+ * @returns The result of sending the update ABI method call
+ */
+ create: async (params: AppClientMethodCallParams & AppClientCompilationParams & SendParams) => {
+ const compiled = await this.compile(params)
+ const results = {
+ ...(await this.processMethodCallReturn(
+ this._algorand.send.appCreateMethodCall(await this.params.create({ ...params })),
+ getArc56Method(params.method, this._appSpec),
+ )),
+ ...(compiled as Partial<AppCompilationResult>),
+ }
+
+ this._appId = results.appId
+ return results
+ },
/**
* Sign and send transactions for an opt-in ABI call
* @param params The parameters for the opt-in ABI method call
@@ -1477,6 +1538,9 @@ export class AppClient {
update: async (params: AppClientMethodCallParams & AppClientCompilationParams) => {
return this._algorand.createTransaction.appUpdateMethodCall(await this.params.update(params))
},
+ create: async (params: AppClientMethodCallParams & AppClientCompilationParams) => {
+ return this._algorand.createTransaction.appCreateMethodCall(await this.params.update(params))
+ },
/**
* Return transactions for an opt-in ABI call
* @param params The parameters for the opt-in ABI method call
@@ -1534,7 +1598,7 @@ export class AppClient {
private getBareParams<
TParams extends { sender?: Address | string; signer?: TransactionSigner | TransactionSignerAccount } | undefined,
TOnComplete extends OnApplicationComplete,
- >(params: TParams, onComplete: TOnComplete) {
+ >(params: TParams, onComplete?: TOnComplete) {
return {
...params,
appId: this._appId,
@@ -1552,7 +1616,7 @@ export class AppClient {
args?: AppClientMethodCallParams['args']
},
TOnComplete extends OnApplicationComplete,
- >(params: TParams, onComplete: TOnComplete) {
+ >(params: TParams, onComplete?: TOnComplete) {
const sender = this.getSender(params.sender)
const method = getArc56Method(params.method, this._appSpec)
const args = await this.getABIArgsWithDefaultValues(params.method, params.args, sender)
diff --git a/src/types/app-deployer.ts b/src/types/app-deployer.ts
index 11db70a2..c2881437 100644
--- a/src/types/app-deployer.ts
+++ b/src/types/app-deployer.ts
@@ -25,6 +25,7 @@ import {
} from './composer'
import { Expand } from './expand'
import { ConfirmedTransactionResult, SendParams } from './transaction'
+import { AppClient } from './app-client'
/** Params to specify an update transaction for an app deployment */
export type DeployAppUpdateParams = Expand<Omit<AppUpdateParams, 'appId' | 'approvalProgram' | 'clearStateProgram'>>
@@ -252,18 +253,18 @@ export class AppDeployer {
)
const result = await ('method' in updateParams
? this._transactionSender.appUpdateMethodCall({
+ ...updateParams,
+ ...sendParams,
appId: existingApp.appId,
approvalProgram,
clearStateProgram,
- ...updateParams,
- ...sendParams,
})
: this._transactionSender.appUpdate({
+ ...updateParams,
+ ...sendParams,
appId: existingApp.appId,
approvalProgram,
clearStateProgram,
- ...updateParams,
- ...sendParams,
}))
const appMetadata: AppMetadata = {
appId: existingApp.appId,
@@ -300,9 +301,9 @@ export class AppDeployer {
}
const createIndex = await composer.count()
if ('method' in deleteParams) {
- composer.addAppDeleteMethodCall({ appId: existingApp.appId, ...deleteParams })
+ composer.addAppDeleteMethodCall({ ...deleteParams, appId: existingApp.appId })
} else {
- composer.addAppDelete({ appId: existingApp.appId, ...deleteParams })
+ composer.addAppDelete({ ...deleteParams, appId: existingApp.appId })
}
const result = await composer.send({ ...sendParams })
const confirmation = result.confirmations.at(createIndex - 1)!
diff --git a/src/types/app-factory.ts b/src/types/app-factory.ts
index 445a5b0d..a6dff028 100644
--- a/src/types/app-factory.ts
+++ b/src/types/app-factory.ts
@@ -1,46 +1,20 @@
import algosdk, { Address } from 'algosdk'
-import { TransactionSignerAccount } from './account'
import { type AlgorandClient } from './algorand-client'
-import {
- AppCompilationResult,
- AppReturn,
- DELETABLE_TEMPLATE_NAME,
- SendAppTransactionResult,
- TealTemplateParams,
- UPDATABLE_TEMPLATE_NAME,
-} from './app'
-import {
- ABIStruct,
- Arc56Contract,
- Arc56Method,
- getABIDecodedValue,
- getABITupleFromABIStruct,
- getArc56Method,
- getArc56ReturnValue,
-} from './app-arc56'
+import { AppCompilationResult, DELETABLE_TEMPLATE_NAME, TealTemplateParams, UPDATABLE_TEMPLATE_NAME } from './app'
+import { Arc56Contract, getArc56Method, getArc56ReturnValue } from './app-arc56'
import {
AppClient,
AppClientBareCallParams,
AppClientCompilationParams,
AppClientMethodCallParams,
- AppClientParams,
AppSourceMaps,
+ CloneAppClientParams,
ResolveAppClientByCreatorAndName,
} from './app-client'
-import {
- AppDeployParams,
- DeployAppDeleteMethodCall,
- DeployAppDeleteParams,
- DeployAppUpdateMethodCall,
- DeployAppUpdateParams,
-} from './app-deployer'
+import { AppDeployParams } from './app-deployer'
import { AppSpec } from './app-spec'
-import { AppCreateMethodCall, AppCreateParams, AppMethodCall, AppMethodCallTransactionArgument, CommonAppCallParams } from './composer'
import { Expand } from './expand'
-import { SendParams } from './transaction'
-import SourceMap = algosdk.ProgramSourceMap
import OnApplicationComplete = algosdk.OnApplicationComplete
-import ABIValue = algosdk.ABIValue
import TransactionSigner = algosdk.TransactionSigner
/** Parameters to create an app client */
@@ -122,17 +96,6 @@ export type CreateSchema = {
extraProgramPages?: number
}
-/** Params to specify a bare (raw) create call for an app */
-export type AppFactoryCreateParams = Expand<AppClientBareCallParams & AppClientCompilationParams & CreateOnComplete & CreateSchema>
-
-/** Params to specify a create method call for an app */
-export type AppFactoryCreateMethodCallParams = Expand<
- AppClientMethodCallParams & AppClientCompilationParams & CreateOnComplete & CreateSchema
->
-
-/** Params to get an app client by ID from an app factory. */
-export type AppFactoryAppClientParams = Expand<Omit<AppClientParams, 'algorand' | 'appSpec'>>
-
/** Params to get an app client by creator address and name from an app factory. */
export type AppFactoryResolveAppClientByCreatorAndNameParams = Expand<Omit<ResolveAppClientByCreatorAndName, 'algorand' | 'appSpec'>>
@@ -178,10 +141,7 @@ export class AppFactory {
private _updatable?: boolean
private _deletable?: boolean
- private _approvalSourceMap: SourceMap | undefined
- private _clearSourceMap: SourceMap | undefined
-
- private _paramsMethods: ReturnType<AppFactory['getParamsMethods']>
+ private _appClient: AppClient
/**
* Create a new app factory.
@@ -204,7 +164,13 @@ export class AppFactory {
this._deployTimeParams = params.deployTimeParams
this._updatable = params.updatable
this._deletable = params.deletable
- this._paramsMethods = this.getParamsMethods()
+ this._appClient = new AppClient({
+ appId: 0n,
+ appSpec: this._appSpec,
+ algorand: this._algorand,
+ defaultSender: this._defaultSender,
+ defaultSigner: this._defaultSigner,
+ })
}
/** The name of the app (from the ARC-32 / ARC-56 app spec or override). */
@@ -238,7 +204,16 @@ export class AppFactory {
* ```
*/
get params() {
- return this._paramsMethods
+ return {
+ create: this._appClient.params.create,
+ deployUpdate: this._appClient.params.update,
+ deployDelete: this._appClient.params.delete,
+ bare: {
+ create: this._appClient.params.bare.create,
+ deployUpdate: this._appClient.params.bare.update,
+ deployDelete: this._appClient.params.bare.delete,
+ },
+ }
}
/** Create transactions for the current app */
@@ -252,7 +227,7 @@ export class AppFactory {
* @param params The parameters to create the create call transaction
* @returns The create call transaction
*/
- create: async (params?: AppFactoryCreateParams) => {
+ create: async (params?: Parameters<typeof AppClient.prototype.params.bare.create>[0]) => {
return this._algorand.createTransaction.appCreate(await this.params.bare.create(params))
},
},
@@ -264,11 +239,23 @@ export class AppFactory {
* @param params The parameters to create the create call transaction
* @returns The create call transaction
*/
- create: async (params: AppFactoryCreateMethodCallParams) => {
+ create: async (params: Parameters<typeof AppClient.prototype.params.create>[0]) => {
return this._algorand.createTransaction.appCreateMethodCall(await this.params.create(params))
},
}
+ private defaultCreateParams() {
+ return {
+ deployTimeParams: this._deployTimeParams,
+ schema: {
+ globalByteSlices: this._appSpec.state.schema.global.bytes,
+ globalInts: this._appSpec.state.schema.global.ints,
+ localByteSlices: this._appSpec.state.schema.local.bytes,
+ localInts: this._appSpec.state.schema.local.ints,
+ },
+ }
+ }
+
/** Send transactions to the current app */
readonly send = {
/** Send bare (raw) transactions for the current app */
@@ -281,23 +268,11 @@ export class AppFactory {
* @param params The parameters to create the app
* @returns The app client and the result of the creation transaction
*/
- create: async (params?: AppFactoryCreateParams & SendParams) => {
- const updatable = params?.updatable ?? this._updatable
- const deletable = params?.deletable ?? this._deletable
- const deployTimeParams = params?.deployTimeParams ?? this._deployTimeParams
- const compiled = await this.compile({ deployTimeParams, updatable, deletable })
- const result = await this.handleCallErrors(async () => ({
- ...(await this._algorand.send.appCreate(await this.params.bare.create({ ...params, updatable, deletable, deployTimeParams }))),
- return: undefined,
- }))
+ create: async (params?: Parameters<typeof AppClient.prototype.send.bare.create>[0]) => {
+ const appClient = this._appClient.clone({})
return {
- appClient: this.getAppClientById({
- appId: result.appId,
- }),
- result: {
- ...result,
- ...(compiled as Partial<AppCompilationResult>),
- },
+ result: await appClient.send.bare.create({ ...this.defaultCreateParams(), ...params }),
+ appClient,
}
},
},
@@ -310,25 +285,11 @@ export class AppFactory {
* @param params The parameters to create the app
* @returns The app client and the result of the creation transaction
*/
- create: async (params: AppFactoryCreateMethodCallParams & SendParams) => {
- const updatable = params?.updatable ?? this._updatable
- const deletable = params?.deletable ?? this._deletable
- const deployTimeParams = params?.deployTimeParams ?? this._deployTimeParams
- const compiled = await this.compile({ deployTimeParams, updatable, deletable })
- const result = await this.handleCallErrors(async () =>
- this.parseMethodCallReturn(
- this._algorand.send.appCreateMethodCall(await this.params.create({ ...params, updatable, deletable, deployTimeParams })),
- getArc56Method(params.method, this._appSpec),
- ),
- )
+ create: async (params: Parameters<typeof AppClient.prototype.send.create>[0]) => {
+ const appClient = this._appClient.clone({})
return {
- appClient: this.getAppClientById({
- appId: result.appId,
- }),
- result: {
- ...result,
- ...(compiled as Partial<AppCompilationResult>),
- },
+ result: await appClient.send.create({ ...this.defaultCreateParams(), ...params }),
+ appClient,
}
},
}
@@ -372,26 +333,21 @@ export class AppFactory {
public async deploy(params: AppFactoryDeployParams) {
const updatable = params.updatable ?? this._updatable ?? this.getDeployTimeControl('updatable')
const deletable = params.deletable ?? this._deletable ?? this.getDeployTimeControl('deletable')
- const deployTimeParams = params.deployTimeParams ?? this._deployTimeParams
+ const deployTimeParams = { ...(params.deployTimeParams ?? this._deployTimeParams) }
- // Compile using a appID 0 AppClient so we can register the error handler and use the programs
- // to identify the app within the error handler (because we can't use app ID 0)
- const tempAppClient = this.getAppClientById({ appId: 0n })
- const compiled = await tempAppClient.compile({ deployTimeParams, updatable, deletable })
+ const compiled = await this._appClient.compile({ deployTimeParams, updatable, deletable })
const deployResult = await this._algorand.appDeployer.deploy({
...params,
createParams: await (params.createParams && 'method' in params.createParams
- ? this.params.create({ ...params.createParams, updatable, deletable, deployTimeParams })
- : this.params.bare.create({ ...params.createParams, updatable, deletable, deployTimeParams })),
- updateParams:
- params.updateParams && 'method' in params.updateParams
- ? this.params.deployUpdate(params.updateParams)
- : this.params.bare.deployUpdate(params.updateParams),
- deleteParams:
- params.deleteParams && 'method' in params.deleteParams
- ? this.params.deployDelete(params.deleteParams)
- : this.params.bare.deployDelete(params.deleteParams),
+ ? this.params.create({ ...this.defaultCreateParams(), ...params.createParams, updatable, deletable, deployTimeParams })
+ : this.params.bare.create({ ...this.defaultCreateParams(), ...params.createParams, updatable, deletable, deployTimeParams })),
+ updateParams: await (params.updateParams && 'method' in params.updateParams
+ ? this.params.deployUpdate({ ...params.updateParams, updatable, deletable, deployTimeParams })
+ : this.params.bare.deployUpdate({ ...params.updateParams, updatable, deletable, deployTimeParams })),
+ deleteParams: await (params.deleteParams && 'method' in params.deleteParams
+ ? this.params.deployDelete(params.deleteParams)
+ : this.params.bare.deployDelete(params.deleteParams)),
metadata: {
name: params.appName ?? this._appName,
version: this._version,
@@ -399,7 +355,7 @@ export class AppFactory {
deletable,
},
})
- const appClient = this.getAppClientById({
+ const appClient = this._appClient.clone({
appId: deployResult.appId,
appName: params.appName,
})
@@ -441,17 +397,8 @@ export class AppFactory {
* const appClient = factory.getAppClientById({ appId: 12345n })
* ```
*/
- public getAppClientById(params: AppFactoryAppClientParams) {
- return new AppClient({
- ...params,
- algorand: this._algorand,
- appSpec: this._appSpec,
- appName: params.appName ?? this._appName,
- defaultSender: params.defaultSender ?? this._defaultSender,
- defaultSigner: params.defaultSigner ?? this._defaultSigner,
- approvalSourceMap: params.approvalSourceMap ?? this._approvalSourceMap,
- clearSourceMap: params.clearSourceMap ?? this._clearSourceMap,
- })
+ public getAppClientById(params: CloneAppClientParams & Required<Pick<CloneAppClientParams, 'appId'>>) {
+ return this._appClient.clone(params)
}
/**
@@ -474,8 +421,8 @@ export class AppFactory {
appSpec: this._appSpec,
appName: params.appName ?? this._appName,
defaultSender: params.defaultSender ?? this._defaultSender,
- approvalSourceMap: params.approvalSourceMap ?? this._approvalSourceMap,
- clearSourceMap: params.clearSourceMap ?? this._clearSourceMap,
+ approvalSourceMap: params.approvalSourceMap ?? this._appClient.exportSourceMaps().approvalSourceMap,
+ clearSourceMap: params.clearSourceMap ?? this._appClient.exportSourceMaps().clearSourceMap,
})
}
@@ -486,12 +433,8 @@ export class AppFactory {
* @param isClearStateProgram Whether or not the code was running the clear state program (defaults to approval program)
* @returns The new error, or if there was no logic error or source map then the wrapped error with source details
*/
- exposeLogicError(e: Error, isClearStateProgram?: boolean): Error {
- return AppClient.exposeLogicError(e, this._appSpec, {
- isClearStateProgram,
- approvalSourceMap: this._approvalSourceMap,
- clearSourceMap: this._clearSourceMap,
- })
+ async exposeLogicError(e: Error, isClearStateProgram?: boolean): Promise<Error> {
+ return await this._appClient.exposeLogicError(e, isClearStateProgram)
}
/**
@@ -499,16 +442,7 @@ export class AppFactory {
* @returns The source maps
*/
exportSourceMaps(): AppSourceMaps {
- if (!this._approvalSourceMap || !this._clearSourceMap) {
- throw new Error(
- "Unable to export source maps; they haven't been loaded into this client - you need to call create, update, or deploy first",
- )
- }
-
- return {
- approvalSourceMap: this._approvalSourceMap,
- clearSourceMap: this._clearSourceMap,
- }
+ return this._appClient.exportSourceMaps()
}
/**
@@ -516,8 +450,7 @@ export class AppFactory {
* @param sourceMaps The source maps to import
*/
importSourceMaps(sourceMaps: AppSourceMaps) {
- this._approvalSourceMap = new SourceMap(sourceMaps.approvalSourceMap)
- this._clearSourceMap = new SourceMap(sourceMaps.clearSourceMap)
+ this._appClient.importSourceMaps(sourceMaps)
}
private getDeployTimeControl(control: 'updatable' | 'deletable'): boolean | undefined {
@@ -534,74 +467,6 @@ export class AppFactory {
)
}
- private getParamsMethods() {
- return {
- /** Return params for a create ABI call, including deploy-time TEAL template replacements and compilation if provided */
- create: async (params: AppFactoryCreateMethodCallParams) => {
- const compiled = await this.compile({ ...params, deployTimeParams: params.deployTimeParams ?? this._deployTimeParams })
- return this.getABIParams(
- {
- ...params,
- deployTimeParams: params.deployTimeParams ?? this._deployTimeParams,
- schema: params.schema ?? {
- globalByteSlices: this._appSpec.state.schema.global.bytes,
- globalInts: this._appSpec.state.schema.global.ints,
- localByteSlices: this._appSpec.state.schema.local.bytes,
- localInts: this._appSpec.state.schema.local.ints,
- },
- approvalProgram: compiled.approvalProgram,
- clearStateProgram: compiled.clearStateProgram,
- },
- params.onComplete ?? OnApplicationComplete.NoOpOC,
- ) satisfies AppCreateMethodCall
- },
- /** Return params for a deployment update ABI call */
- deployUpdate: (params: AppClientMethodCallParams) => {
- return this.getABIParams(params, OnApplicationComplete.UpdateApplicationOC) satisfies DeployAppUpdateMethodCall
- },
- /** Return params for a deployment delete ABI call */
- deployDelete: (params: AppClientMethodCallParams) => {
- return this.getABIParams(params, OnApplicationComplete.DeleteApplicationOC) satisfies DeployAppDeleteMethodCall
- },
- bare: {
- /** Return params for a create bare call, including deploy-time TEAL template replacements and compilation if provided */
- create: async (params?: AppFactoryCreateParams) => {
- return this.getBareParams(
- {
- ...params,
- deployTimeParams: params?.deployTimeParams ?? this._deployTimeParams,
- schema: params?.schema ?? {
- globalByteSlices: this._appSpec.state.schema.global.bytes,
- globalInts: this._appSpec.state.schema.global.ints,
- localByteSlices: this._appSpec.state.schema.local.bytes,
- localInts: this._appSpec.state.schema.local.ints,
- },
- ...(await this.compile({ ...params, deployTimeParams: params?.deployTimeParams ?? this._deployTimeParams })),
- },
- params?.onComplete ?? OnApplicationComplete.NoOpOC,
- ) satisfies AppCreateParams
- },
- /** Return params for a deployment update bare call */
- deployUpdate: (params?: AppClientBareCallParams) => {
- return this.getBareParams(params, OnApplicationComplete.UpdateApplicationOC) satisfies DeployAppUpdateParams
- },
- /** Return params for a deployment delete bare call */
- deployDelete: (params?: AppClientBareCallParams) => {
- return this.getBareParams(params, OnApplicationComplete.DeleteApplicationOC) satisfies DeployAppDeleteParams
- },
- },
- }
- }
-
- /** Make the given call and catch any errors, augmenting with debugging information before re-throwing. */
- private async handleCallErrors<TResult>(call: () => Promise<TResult>) {
- try {
- return await call()
- } catch (e) {
- throw this.exposeLogicError(e as Error)
- }
- }
-
/**
* Compiles the approval and clear state programs (if TEAL templates provided),
* performing any provided deploy-time parameter replacement and stores
@@ -618,109 +483,6 @@ export class AppFactory {
* ```
*/
public async compile(compilation?: AppClientCompilationParams) {
- const result = await AppClient.compile(this._appSpec, this._algorand.app, compilation)
-
- if (result.compiledApproval) {
- this._approvalSourceMap = result.compiledApproval.sourceMap
- }
- if (result.compiledClear) {
- this._clearSourceMap = result.compiledClear.sourceMap
- }
-
- return result
- }
-
- private getBareParams<
- TParams extends { sender?: Address | string; signer?: TransactionSigner | TransactionSignerAccount } | undefined,
- TOnComplete extends OnApplicationComplete,
- >(params: TParams, onComplete: TOnComplete) {
- return {
- ...params,
- sender: this.getSender(params?.sender),
- signer: this.getSigner(params?.sender, params?.signer),
- onComplete,
- }
- }
-
- private getABIParams<
- TParams extends {
- method: string
- sender?: Address | string
- signer?: TransactionSigner | TransactionSignerAccount
- args?: AppClientMethodCallParams['args']
- },
- TOnComplete extends OnApplicationComplete,
- >(params: TParams, onComplete: TOnComplete) {
- return {
- ...params,
- sender: this.getSender(params.sender),
- signer: this.getSigner(params.sender, params.signer),
- method: getArc56Method(params.method, this._appSpec),
- args: this.getCreateABIArgsWithDefaultValues(params.method, params.args),
- onComplete,
- }
- }
-
- private getCreateABIArgsWithDefaultValues(
- methodNameOrSignature: string,
- args: AppClientMethodCallParams['args'] | undefined,
- ): AppMethodCall<CommonAppCallParams>['args'] {
- const m = getArc56Method(methodNameOrSignature, this._appSpec)
- return args?.map((a, i) => {
- const arg = m.args[i]
- if (a !== undefined) {
- // If a struct then convert to tuple for the underlying call
- return arg.struct && typeof a === 'object' && !Array.isArray(a)
- ? getABITupleFromABIStruct(a as ABIStruct, this._appSpec.structs[arg.struct], this._appSpec.structs)
- : (a as ABIValue | AppMethodCallTransactionArgument)
- }
- const defaultValue = arg.defaultValue
- if (defaultValue) {
- switch (defaultValue.source) {
- case 'literal':
- return getABIDecodedValue(Buffer.from(defaultValue.data, 'base64'), m.method.args[i].type, this._appSpec.structs) as ABIValue
- default:
- throw new Error(`Can't provide default value for ${defaultValue.source} for a contract creation call`)
- }
- }
- throw new Error(`No value provided for required argument ${arg.name ?? `arg${i + 1}`} in call to method ${m.name}`)
- })
- }
-
- /** Returns the sender for a call, using the `defaultSender`
- * if none provided and throws an error if neither provided */
- private getSender(sender: string | Address | undefined): Address {
- if (!sender && !this._defaultSender) {
- throw new Error(`No sender provided and no default sender present in app factory for call to app ${this._appName}`)
- }
- return typeof sender === 'string' ? Address.fromString(sender) : (sender ?? this._defaultSender!)
- }
-
- /** Returns the signer for a call, using the provided signer or the `defaultSigner`
- * if no signer was provided and the sender resolves to the default sender, the call will use default signer
- * or `undefined` otherwise (so the signer is resolved from `AlgorandClient`) */
- private getSigner(
- sender: Address | string | undefined,
- signer: TransactionSigner | TransactionSignerAccount | undefined,
- ): TransactionSigner | TransactionSignerAccount | undefined {
- return signer ?? (!sender || sender === this._defaultSender ? this._defaultSigner : undefined)
- }
-
- /**
- * Checks for decode errors on the SendAppTransactionResult and maps the return value to the specified type
- * on the ARC-56 method.
- *
- * If the return type is a struct then the struct will be returned.
- *
- * @param result The SendAppTransactionResult to be mapped
- * @param method The method that was called
- * @returns The smart contract response with an updated return value
- */
- async parseMethodCallReturn<
- TReturn extends Uint8Array | ABIValue | ABIStruct | undefined,
- TResult extends SendAppTransactionResult = SendAppTransactionResult,
- >(result: Promise<TResult> | TResult, method: Arc56Method): Promise<Omit<TResult, 'return'> & AppReturn<TReturn>> {
- const resultValue = await result
- return { ...resultValue, return: getArc56ReturnValue(resultValue.return, method, this._appSpec.structs) }
+ return this._appClient.compile(compilation)
}
}