Skip to content

Commit 44e6baf

Browse files
PhearZeromeetthosar
andcommitted
feat: application call transactions
Co-authored-by: Meet Thosar <meetthosar@gmail.com>
1 parent 2ccff29 commit 44e6baf

File tree

5 files changed

+452
-1
lines changed

5 files changed

+452
-1
lines changed

lib/algorand.transaction.appl.ts

Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
import {AlgorandEncoder} from "./algorand.encoder.js"
2+
import {ITransactionHeaderBuilder, TransactionHeader} from "./algorand.transaction.header";
3+
4+
/**
5+
* Represents the schema of the state used within an application.
6+
*
7+
* @category Common
8+
* @since v1.0.0
9+
*/
10+
export type StateSchema = {
11+
/**
12+
* Maximum number of integer values that may be stored in
13+
* the [global || local] application key/value store.
14+
*
15+
* Immutable.
16+
*/
17+
nui: number
18+
/**
19+
* Maximum number of byte slices values that may be stored in
20+
* the [global || local] application key/value store.
21+
*
22+
* Immutable.
23+
*/
24+
nbs: number
25+
}
26+
27+
/**
28+
* Includes all fields in {@link TransactionHeader} and "type" is "appl".
29+
*
30+
* @category Transactions
31+
* @see {@link AlgorandTransactionCrafter}
32+
* @see {@link ApplicationCallTxBuilder}
33+
* @since v1.0.0
34+
*/
35+
export class ApplicationCallTransaction extends TransactionHeader {
36+
declare type: "appl"
37+
/**
38+
* Application ID
39+
*
40+
* ID of the application being configured or empty if creating.
41+
*/
42+
apid: bigint // Application id (required)
43+
/**
44+
* OnComplete
45+
*
46+
* Defines what additional actions occur with the transaction.
47+
*
48+
* An application transaction must indicate the action to be taken following the execution of its approvalProgram or clearStateProgram.
49+
* The constants below describe the available actions.
50+
*
51+
* | Value | Name | Description |
52+
* |-------|------|-------------|
53+
* | 0 | NoOp | Only execute the ApprovalProgram associated with this application ID, with no additional effects. |
54+
* | 1 | OptIn | Before executing the ApprovalProgram, allocate the local state for this application into the sender's account data. |
55+
* | 2 | CloseOut | After executing the ApprovalProgram, clear any local state for this application out of the sender's account data. |
56+
* | 3 | ClearState | Don't execute the ApprovalProgram, and instead execute the ClearStateProgram (which may not reject this transaction). Additionally, clear any local state for this application out of the sender's account data as in CloseOutOC. |
57+
* | 4 | UpdateApplication | After executing the ApprovalProgram, replace the ApprovalProgram and ClearStateProgram associated with this application ID with the programs specified in this transaction. |
58+
* | 5 | DeleteApplication | After executing the ApprovalProgram, delete the application parameters from the account data of the application's creator. |
59+
*/
60+
apan: number // #onComplete (required)
61+
/**
62+
* Accounts
63+
*
64+
* List of accounts in addition to the sender that may be accessed from the
65+
* application's approval-program and clear-state-program.
66+
*/
67+
apat?: Uint8Array[] // Accounts
68+
/**
69+
* Approval Program
70+
*
71+
* Logic executed for every application transaction, except when on-completion is set to "clear".
72+
* It can read and write global state for the application, as well as account-specific local state.
73+
* Approval programs may reject the transaction.
74+
*/
75+
apap?: Uint8Array // Approval program
76+
/**
77+
* App Arguments
78+
*
79+
* Transaction-specific arguments accessed from the application's approval-program and clear-state-program.
80+
*/
81+
apaa?: Uint8Array[] // Application arguments
82+
/**
83+
* Clear State Program
84+
*
85+
* Logic executed for application transactions with on-completion set to "clear".
86+
* It can read and write global state for the application, as well as account-specific local state.
87+
* Clear state programs cannot reject the transaction.
88+
*/
89+
apsu?: Uint8Array // Clear state program
90+
/**
91+
* Foreign Apps
92+
*
93+
* Lists the applications in addition to the application-id whose global states may
94+
* be accessed by this application's approval-program and clear-state-program.
95+
* The access is read-only.
96+
*/
97+
apfa?: bigint[] // Foreign apps (check)
98+
/**
99+
* Foreign Assets
100+
*
101+
* Lists the assets whose AssetParams may be accessed by this application's approval-program and clear-state-program. The access is read-only.
102+
*/
103+
apas?: bigint[] // Foreign assets (check)
104+
/**
105+
* Global {@link StateSchema}
106+
*
107+
* Holds the maximum number of global state values defined within a {@link StateSchema} object.
108+
*/
109+
apgs?: StateSchema; // Global schema
110+
/**
111+
* Local {@link StateSchema}
112+
*
113+
* Holds the maximum number of local state values defined within a {@link StateSchema} object.
114+
*/
115+
apls?: StateSchema; // Local schema
116+
/**
117+
* Extra Program Pages
118+
*
119+
* Number of additional pages allocated to the application's approval and clear state programs.
120+
* Each ExtraProgramPages is 2048 bytes.
121+
* The sum of ApprovalProgram and ClearStateProgram may not exceed 2048*(1+ExtraProgramPages) bytes.
122+
*/
123+
apep?: number // Extra program
124+
/**
125+
* Boxes
126+
*
127+
* The boxes that should be made available for the runtime of the program.
128+
*/
129+
apbx?: {
130+
i: number
131+
n: string
132+
}[] // Boxes
133+
/**
134+
* Encodes the current transaction object into a Uint8Array using the Algorand transaction encoding format.
135+
*
136+
* @return {Uint8Array} The encoded transaction as a Uint8Array.
137+
*/
138+
encode(): Uint8Array {
139+
return new AlgorandEncoder().encodeTransaction(this)
140+
}
141+
}
142+
/**
143+
* Interface representing a builder for creating Application Call transactions.
144+
* This builder provides methods to configure various attributes of an Application Call transaction.
145+
*
146+
* @category Builders
147+
* @protected
148+
* @since v1.0.0
149+
*/
150+
export interface IApplicationCallTxBuilder extends ITransactionHeaderBuilder<IApplicationCallTxBuilder> {
151+
/**
152+
* {@inheritDoc ApplicationCallTransaction#apid}
153+
* @param {bigint} apid - The unique identifier of the application to be called.
154+
*/
155+
addApplicationId(apid: bigint): IApplicationCallTxBuilder;
156+
/**
157+
* {@inheritDoc ApplicationCallTransaction#apan}
158+
* @param {number} apan - which action to take
159+
*/
160+
addOnComplete(apan: number): IApplicationCallTxBuilder;
161+
/**
162+
* {@inheritDoc ApplicationCallTransaction#apat}
163+
* @param {string[]} apat - An array of account addresses to be added.
164+
*/
165+
addAccounts(apat: string[]): IApplicationCallTxBuilder;
166+
/**
167+
* {@inheritDoc ApplicationCallTransaction#apap}
168+
* @param {Uint8Array} apap - The approval program bytes to be added to the transaction.
169+
*/
170+
addApprovalProgram(apap: Uint8Array): IApplicationCallTxBuilder;
171+
/**
172+
* {@inheritDoc ApplicationCallTransaction#apaa}
173+
* @param {Uint8Array[]} apaa - Application arguments in bytes
174+
*/
175+
addApplicationArgs(apaa: Uint8Array[]): IApplicationCallTxBuilder;
176+
/**
177+
* {@inheritDoc ApplicationCallTransaction#apsu}
178+
* @param {Uint8Array} apsu - The clear state program bytes to be added
179+
*/
180+
addClearStateProgram(apsu: Uint8Array): IApplicationCallTxBuilder;
181+
/**
182+
* {@inheritDoc ApplicationCallTransaction#apfa}
183+
* @param {bigint[]} apfa - List of foreign application ids
184+
*/
185+
addForeignApps(apfa: bigint[]): IApplicationCallTxBuilder;
186+
/**
187+
* {@inheritDoc ApplicationCallTransaction#apas}
188+
* @param {bigint[]} apas - List of foreign assets ids
189+
*/
190+
addForeignAssets(apas: bigint[]): IApplicationCallTxBuilder;
191+
/**
192+
* {@inheritDoc ApplicationCallTransaction#apgs}
193+
* @param {StateSchema} apgs - Global state schema
194+
*/
195+
addGlobalSchema(apgs: StateSchema): IApplicationCallTxBuilder;
196+
/**
197+
* {@inheritDoc ApplicationCallTransaction#apls}
198+
* @param {StateSchema} apls - Global state schema
199+
*/
200+
addLocalSchema(apls: StateSchema): IApplicationCallTxBuilder;
201+
/**
202+
* {@inheritDoc ApplicationCallTransaction#apep}
203+
* @param {StateSchema} apep - Number of pages to add
204+
*/
205+
addExtraProgramPages(apep: number): IApplicationCallTxBuilder;
206+
/**
207+
* {@inheritDoc ApplicationCallTransaction#apbx}
208+
* @param apbx - List of boxes
209+
*/
210+
addBoxes(apbx: { i: number; n: string }[]): IApplicationCallTxBuilder;
211+
212+
/**
213+
* Validate the model and return the instance
214+
*/
215+
get(): ApplicationCallTransaction;
216+
}
217+
218+
/**
219+
* Class to build an Algorand Application Call Transaction with a fluent interface.
220+
* This class provides methods to configure various properties of the transaction.
221+
*
222+
* This builder can be used to interact with a {@link ApplicationCallTransaction}
223+
*
224+
*
225+
* @category Builders
226+
* @see {@link AlgorandTransactionCrafter}
227+
* @since v1.0.0
228+
*/
229+
export class ApplicationCallTxBuilder implements IApplicationCallTxBuilder {
230+
private readonly tx: ApplicationCallTransaction
231+
private readonly encoder: AlgorandEncoder
232+
233+
constructor(genesisId: string, genesisHash: string) {
234+
this.encoder = new AlgorandEncoder()
235+
236+
this.tx = new ApplicationCallTransaction();
237+
this.tx.gen = genesisId;
238+
this.tx.gh = new Uint8Array(Buffer.from(genesisHash, "base64"));
239+
this.tx.type = "appl";
240+
this.tx.fee = 1000n;
241+
}
242+
243+
addApplicationId(appId: bigint): IApplicationCallTxBuilder {
244+
this.tx.apid = appId;
245+
return this;
246+
}
247+
248+
addOnComplete(apan: number): IApplicationCallTxBuilder {
249+
this.tx.apan = apan;
250+
return this;
251+
}
252+
253+
addAccounts(apat: string[]): IApplicationCallTxBuilder {
254+
this.tx.apat = apat.map(account => new AlgorandEncoder().decodeAddress(account));
255+
return this;
256+
}
257+
addApprovalProgram(apap: Uint8Array): IApplicationCallTxBuilder {
258+
this.tx.apap = apap;
259+
return this;
260+
}
261+
addApplicationArgs(apaa: Uint8Array[]): IApplicationCallTxBuilder {
262+
this.tx.apaa = apaa;
263+
return this;
264+
}
265+
addClearStateProgram(apsu: Uint8Array): IApplicationCallTxBuilder {
266+
this.tx.apsu = apsu;
267+
return this;
268+
}
269+
270+
addForeignApps(apps: bigint[]): IApplicationCallTxBuilder {
271+
this.tx.apas = apps;
272+
return this;
273+
}
274+
addForeignAssets(apfa: bigint[]): IApplicationCallTxBuilder {
275+
this.tx.apfa = apfa;
276+
return this;
277+
}
278+
addGlobalSchema(apgs: StateSchema): IApplicationCallTxBuilder {
279+
this.tx.apgs = apgs;
280+
return this;
281+
}
282+
addLocalSchema(apls: StateSchema): IApplicationCallTxBuilder {
283+
this.tx.apls = apls;
284+
return this;
285+
}
286+
287+
addExtraProgramPages(apep: number): IApplicationCallTxBuilder {
288+
this.tx.apep = apep;
289+
return this;
290+
}
291+
addBoxes(apbx: { i: number; n: string }[]): IApplicationCallTxBuilder {
292+
this.tx.apbx = apbx;
293+
return this;
294+
}
295+
addSender(sender: string): IApplicationCallTxBuilder {
296+
this.tx.snd = this.encoder.decodeAddress(sender)
297+
return this
298+
}
299+
addFee(fee: number | bigint): IApplicationCallTxBuilder {
300+
this.tx.fee = AlgorandEncoder.safeCastBigInt(fee)
301+
return this
302+
}
303+
addFirstValidRound(firstValid: number | bigint): IApplicationCallTxBuilder {
304+
this.tx.fv = AlgorandEncoder.safeCastBigInt(firstValid)
305+
return this
306+
}
307+
addLastValidRound(lastValid: number | bigint): IApplicationCallTxBuilder {
308+
this.tx.lv = AlgorandEncoder.safeCastBigInt(lastValid)
309+
return this
310+
}
311+
addNote(note: string, encoding: BufferEncoding = "utf8"): IApplicationCallTxBuilder {
312+
this.tx.note = new Uint8Array(Buffer.from(note, encoding))
313+
return this
314+
}
315+
addRekey(address: string): IApplicationCallTxBuilder {
316+
this.tx.rekey = this.encoder.decodeAddress(address)
317+
return this
318+
}
319+
addLease(lease: Uint8Array): IApplicationCallTxBuilder {
320+
this.tx.lx = lease
321+
return this
322+
}
323+
addGroup(group: Uint8Array): IApplicationCallTxBuilder {
324+
this.tx.grp = group
325+
return this
326+
}
327+
get(): ApplicationCallTransaction {
328+
return this.tx;
329+
}
330+
}

lib/algorand.transaction.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {AssetConfigTransaction} from "./algorand.transaction.acfg.js";
33
import {AssetTransferTransaction} from "./algorand.transaction.axfer.js";
44
import {AssetFreezeTransaction} from "./algorand.transaction.afrz.js";
55
import {KeyregTransaction} from "./algorand.transaction.keyreg.js";
6+
import {ApplicationCallTransaction} from "./algorand.transaction.appl";
67

78
/**
89
* Transaction Alias
@@ -11,7 +12,7 @@ import {KeyregTransaction} from "./algorand.transaction.keyreg.js";
1112
*
1213
* @category Common
1314
*/
14-
export type Transaction = PayTransaction | AssetConfigTransaction | AssetTransferTransaction | AssetFreezeTransaction | KeyregTransaction
15+
export type Transaction = PayTransaction | AssetConfigTransaction | AssetTransferTransaction | AssetFreezeTransaction | KeyregTransaction | ApplicationCallTransaction
1516

1617
// SignedTransaction
1718
export interface SignedTransaction {

lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export * from './algorand.transaction.crafter.js'
99
// Transactions/Builders
1010
export * from './algorand.transaction.acfg.js'
1111
export * from './algorand.transaction.afrz.js'
12+
export * from './algorand.transaction.appl.js'
1213
export * from './algorand.transaction.axfer.js'
1314
export * from './algorand.transaction.keyreg.js'
1415
export * from './algorand.transaction.pay.js'

0 commit comments

Comments
 (0)