algosdk 3.7.0-beta.1 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +4 -4
  2. package/dist/browser/algosdk.min.js +1 -1
  3. package/dist/browser/algosdk.min.js.map +1 -1
  4. package/dist/cjs/appAccess.js +4 -0
  5. package/dist/cjs/appAccess.js.map +1 -1
  6. package/dist/cjs/client/v2/algod/models/types.js +153 -5
  7. package/dist/cjs/client/v2/algod/models/types.js.map +1 -1
  8. package/dist/cjs/client/v2/indexer/models/types.js +163 -12
  9. package/dist/cjs/client/v2/indexer/models/types.js.map +1 -1
  10. package/dist/cjs/composer.js +4 -6
  11. package/dist/cjs/composer.js.map +1 -1
  12. package/dist/cjs/falcon-signer.js.map +1 -1
  13. package/dist/cjs/heartbeat.js +7 -0
  14. package/dist/cjs/heartbeat.js.map +1 -1
  15. package/dist/cjs/makeTxn.js +11 -2
  16. package/dist/cjs/makeTxn.js.map +1 -1
  17. package/dist/cjs/pq-signer.js +26 -0
  18. package/dist/cjs/pq-signer.js.map +1 -1
  19. package/dist/cjs/signer.js.map +1 -1
  20. package/dist/cjs/transaction.js +8 -0
  21. package/dist/cjs/transaction.js.map +1 -1
  22. package/dist/cjs/types/statedelta.js +17 -0
  23. package/dist/cjs/types/statedelta.js.map +1 -1
  24. package/dist/cjs/utils/utils.js +14 -1
  25. package/dist/cjs/utils/utils.js.map +1 -1
  26. package/dist/esm/appAccess.js +4 -0
  27. package/dist/esm/appAccess.js.map +1 -1
  28. package/dist/esm/client/v2/algod/models/types.js +149 -3
  29. package/dist/esm/client/v2/algod/models/types.js.map +1 -1
  30. package/dist/esm/client/v2/indexer/models/types.js +161 -11
  31. package/dist/esm/client/v2/indexer/models/types.js.map +1 -1
  32. package/dist/esm/composer.js +4 -6
  33. package/dist/esm/composer.js.map +1 -1
  34. package/dist/esm/falcon-signer.js.map +1 -1
  35. package/dist/esm/heartbeat.js +8 -1
  36. package/dist/esm/heartbeat.js.map +1 -1
  37. package/dist/esm/makeTxn.js +11 -2
  38. package/dist/esm/makeTxn.js.map +1 -1
  39. package/dist/esm/pq-signer.js +26 -0
  40. package/dist/esm/pq-signer.js.map +1 -1
  41. package/dist/esm/signer.js.map +1 -1
  42. package/dist/esm/transaction.js +8 -0
  43. package/dist/esm/transaction.js.map +1 -1
  44. package/dist/esm/types/statedelta.js +17 -0
  45. package/dist/esm/types/statedelta.js.map +1 -1
  46. package/dist/esm/utils/utils.js +12 -0
  47. package/dist/esm/utils/utils.js.map +1 -1
  48. package/dist/types/client/v2/algod/models/types.d.ts +90 -3
  49. package/dist/types/client/v2/indexer/models/types.d.ts +114 -7
  50. package/dist/types/composer.d.ts +3 -3
  51. package/dist/types/falcon-signer.d.ts +2 -2
  52. package/dist/types/heartbeat.d.ts +2 -0
  53. package/dist/types/makeTxn.d.ts +8 -2
  54. package/dist/types/pq-signer.d.ts +2 -2
  55. package/dist/types/signer.d.ts +8 -0
  56. package/dist/types/transaction.d.ts +1 -0
  57. package/dist/types/types/statedelta.d.ts +18 -0
  58. package/dist/types/types/transactions/base.d.ts +10 -0
  59. package/dist/types/utils/utils.d.ts +1 -0
  60. package/package.json +2 -2
  61. package/src/appAccess.ts +5 -0
  62. package/src/client/v2/algod/models/types.ts +234 -0
  63. package/src/client/v2/indexer/models/types.ts +280 -8
  64. package/src/composer.ts +7 -11
  65. package/src/falcon-signer.ts +4 -1
  66. package/src/heartbeat.ts +11 -0
  67. package/src/makeTxn.ts +13 -4
  68. package/src/pq-signer.ts +34 -1
  69. package/src/signer.ts +9 -0
  70. package/src/transaction.ts +10 -0
  71. package/src/types/statedelta.ts +34 -0
  72. package/src/types/transactions/base.ts +11 -0
  73. package/src/utils/utils.ts +13 -0
package/src/heartbeat.ts CHANGED
@@ -2,6 +2,7 @@ import { Address } from './encoding/address.js';
2
2
  import { Encodable, Schema } from './encoding/encoding.js';
3
3
  import {
4
4
  AddressSchema,
5
+ BooleanSchema,
5
6
  Uint64Schema,
6
7
  ByteArraySchema,
7
8
  FixedLengthByteArraySchema,
@@ -111,6 +112,10 @@ export class Heartbeat implements Encodable {
111
112
  key: 'kd', // HbKeyDilution
112
113
  valueSchema: new Uint64Schema(),
113
114
  },
115
+ {
116
+ key: 'c', // HbChallengeDiscount
117
+ valueSchema: new BooleanSchema(),
118
+ },
114
119
  ])
115
120
  );
116
121
 
@@ -124,18 +129,22 @@ export class Heartbeat implements Encodable {
124
129
 
125
130
  public keyDilution: bigint;
126
131
 
132
+ public challengeDiscount: boolean;
133
+
127
134
  public constructor(params: {
128
135
  address: Address;
129
136
  proof: HeartbeatProof;
130
137
  seed: Uint8Array;
131
138
  voteID: Uint8Array;
132
139
  keyDilution: bigint;
140
+ challengeDiscount?: boolean;
133
141
  }) {
134
142
  this.address = params.address;
135
143
  this.proof = params.proof;
136
144
  this.seed = params.seed;
137
145
  this.voteID = params.voteID;
138
146
  this.keyDilution = params.keyDilution;
147
+ this.challengeDiscount = params.challengeDiscount ?? false;
139
148
  }
140
149
 
141
150
  // eslint-disable-next-line class-methods-use-this
@@ -150,6 +159,7 @@ export class Heartbeat implements Encodable {
150
159
  ['sd', this.seed],
151
160
  ['vid', this.voteID],
152
161
  ['kd', this.keyDilution],
162
+ ['c', this.challengeDiscount],
153
163
  ]);
154
164
  }
155
165
 
@@ -163,6 +173,7 @@ export class Heartbeat implements Encodable {
163
173
  seed: data.get('sd'),
164
174
  voteID: data.get('vid'),
165
175
  keyDilution: data.get('kd'),
176
+ challengeDiscount: data.get('c'),
166
177
  });
167
178
  }
168
179
  }
package/src/makeTxn.ts CHANGED
@@ -539,7 +539,13 @@ export function makeApplicationCreateTxnFromObject({
539
539
  }
540
540
 
541
541
  /**
542
- * Make a transaction that changes an application's approval and clear programs
542
+ * Make a transaction that changes an application's approval and clear programs.
543
+ *
544
+ * The application's global state schema and extra program pages may also be changed during an
545
+ * update by providing numGlobalInts, numGlobalByteSlices, and/or extraPages. The local state schema
546
+ * cannot be changed after application creation. If the pages or global schema increases in size, the entire
547
+ * MBR for the application will move to the sender of the update and that account will become the `sizeSponsor`
548
+ * in the application's parameters. A decrease in schema or pages does not affect MBR or `sizeSponsor`.
543
549
  *
544
550
  * @param options - Application update transaction parameters
545
551
  */
@@ -557,6 +563,9 @@ export function makeApplicationUpdateTxnFromObject({
557
563
  access,
558
564
  approvalProgram,
559
565
  clearProgram,
566
+ numGlobalInts,
567
+ numGlobalByteSlices,
568
+ extraPages,
560
569
  note,
561
570
  lease,
562
571
  rekeyTo,
@@ -566,9 +575,6 @@ export function makeApplicationUpdateTxnFromObject({
566
575
  | 'onComplete'
567
576
  | 'numLocalInts'
568
577
  | 'numLocalByteSlices'
569
- | 'numGlobalInts'
570
- | 'numGlobalByteSlices'
571
- | 'extraPages'
572
578
  | 'approvalProgram'
573
579
  | 'clearProgram'
574
580
  > &
@@ -598,6 +604,9 @@ export function makeApplicationUpdateTxnFromObject({
598
604
  access,
599
605
  approvalProgram,
600
606
  clearProgram,
607
+ numGlobalInts,
608
+ numGlobalByteSlices,
609
+ extraPages,
601
610
  note,
602
611
  lease,
603
612
  rekeyTo,
package/src/pq-signer.ts CHANGED
@@ -5,6 +5,7 @@ import { MultisigMetadata } from './multisig.js';
5
5
  import { SignedTransaction } from './signedTransaction.js';
6
6
  import {
7
7
  AddressWithDelegatedLsigSigner,
8
+ AddressWithEmptyTransactionSigner,
8
9
  AddressWithTransactionSigner,
9
10
  DelegatedLsigSigner,
10
11
  TransactionSigner,
@@ -22,7 +23,9 @@ export interface PQSigningKey {
22
23
  export function addressWithSignersFromRawPQSigner(
23
24
  signingKey: PQSigningKey,
24
25
  sendingAddress?: Address
25
- ): AddressWithTransactionSigner & AddressWithDelegatedLsigSigner {
26
+ ): AddressWithTransactionSigner &
27
+ AddressWithDelegatedLsigSigner &
28
+ AddressWithEmptyTransactionSigner {
26
29
  const { pqPublicKey, pqSigner: rawSigner, pqScheme } = signingKey;
27
30
  const { address: authAddress, salt } = addressFromPQKey(
28
31
  pqScheme,
@@ -56,6 +59,35 @@ export function addressWithSignersFromRawPQSigner(
56
59
  return stxns.map((stxn) => encodeMsgpack(stxn));
57
60
  };
58
61
 
62
+ // A TransactionSigner that attaches a placeholder PQ envelope rather than a
63
+ // real signature. The scheme, salt, and public key are populated but the
64
+ // signature bytes are left empty. When simulated with `allowEmptySignatures`,
65
+ // algod derives the authorizer from this envelope and charges the post-quantum
66
+ // fee surcharge, so the reported fee usage matches a genuinely signed group -
67
+ // all without paying the cost of producing a (large, slow) Falcon signature.
68
+ const emptyTxnSigner: TransactionSigner = (
69
+ txnGroup: Transaction[],
70
+ indexesToSign: number[]
71
+ ) => {
72
+ const stxns: Uint8Array[] = [];
73
+ for (const index of indexesToSign) {
74
+ const txn = txnGroup[index];
75
+ const pqsig: EncodedPQSig = {
76
+ sch: pqScheme,
77
+ slt: salt,
78
+ pk: pqPublicKey,
79
+ sig: new Uint8Array(),
80
+ };
81
+ const stxn = new SignedTransaction({
82
+ txn,
83
+ pqsig,
84
+ sgnr: txn.sender.equals(authAddress) ? undefined : authAddress,
85
+ });
86
+ stxns.push(encodeMsgpack(stxn));
87
+ }
88
+ return Promise.resolve(stxns);
89
+ };
90
+
59
91
  const delegatedLsigSigner: DelegatedLsigSigner = async (
60
92
  lsig: LogicSig,
61
93
  msig?: MultisigMetadata
@@ -85,6 +117,7 @@ export function addressWithSignersFromRawPQSigner(
85
117
  return {
86
118
  address: sendingAddress ?? authAddress,
87
119
  txnSigner,
120
+ emptyTxnSigner,
88
121
  delegatedLsigSigner,
89
122
  };
90
123
  }
package/src/signer.ts CHANGED
@@ -40,6 +40,15 @@ export interface AddressWithTransactionSigner extends Addressable {
40
40
  txnSigner: TransactionSigner;
41
41
  }
42
42
 
43
+ export interface AddressWithEmptyTransactionSigner extends Addressable {
44
+ /**
45
+ * A TransactionSigner that produces unsigned (or placeholder-signed)
46
+ * transactions. This must only be used to simulate transactions with the
47
+ * `allowEmptySignatures` option enabled.
48
+ */
49
+ emptyTxnSigner: TransactionSigner;
50
+ }
51
+
43
52
  /** Function for signing logic signatures for delegation
44
53
  * @param lsig - The logic signature that is being signed for delegation
45
54
  * @param msig - Optional multisig account that should be set when a public key is signing as a subsigner of a multisig
@@ -247,6 +247,12 @@ function ensureResourceReference(input: unknown): TransactionResourceReference {
247
247
  if (box !== undefined) {
248
248
  return { box: ensureBoxReference(box) };
249
249
  }
250
+
251
+ // An empty resource reference is meaningful: it asks for a box I/O quota
252
+ // bump without naming a resource.
253
+ if (utils.isEmptyObject(input)) {
254
+ return {};
255
+ }
250
256
  }
251
257
  throw new Error(`Not a resource reference: ${input}`);
252
258
  }
@@ -329,6 +335,7 @@ export interface HeartbeatTransactionFields {
329
335
  readonly seed: Uint8Array;
330
336
  readonly voteID: Uint8Array;
331
337
  readonly keyDilution: bigint;
338
+ readonly challengeDiscount: boolean;
332
339
  }
333
340
 
334
341
  /**
@@ -876,6 +883,7 @@ export class Transaction implements encoding.Encodable {
876
883
  seed: params.heartbeatParams.seed,
877
884
  voteID: params.heartbeatParams.voteID,
878
885
  keyDilution: params.heartbeatParams.keyDilution,
886
+ challengeDiscount: params.heartbeatParams.challengeDiscount,
879
887
  });
880
888
  }
881
889
 
@@ -1035,6 +1043,7 @@ export class Transaction implements encoding.Encodable {
1035
1043
  seed: this.heartbeat.seed,
1036
1044
  voteID: this.heartbeat.voteID,
1037
1045
  keyDilution: this.heartbeat.keyDilution,
1046
+ challengeDiscount: this.heartbeat.challengeDiscount,
1038
1047
  });
1039
1048
  data.set('hb', heartbeat.toEncodingData());
1040
1049
  return data;
@@ -1219,6 +1228,7 @@ export class Transaction implements encoding.Encodable {
1219
1228
  seed: heartbeat.seed,
1220
1229
  voteID: heartbeat.voteID,
1221
1230
  keyDilution: heartbeat.keyDilution,
1231
+ challengeDiscount: heartbeat.challengeDiscount,
1222
1232
  };
1223
1233
  params.heartbeatParams = heartbeatParams;
1224
1234
  } else {
@@ -139,6 +139,10 @@ export class AppParams implements Encodable {
139
139
  { key: 'lsch', valueSchema: StateSchema.encodingSchema }, // localStateSchema
140
140
  { key: 'gsch', valueSchema: StateSchema.encodingSchema }, // globalStateSchema
141
141
  { key: 'epp', valueSchema: new Uint64Schema() }, // extraProgramPages
142
+ { key: 'v', valueSchema: new Uint64Schema() }, // version
143
+ { key: 'ss', valueSchema: new AddressSchema() }, // sizeSponsor
144
+ { key: 'fbr', valueSchema: new BooleanSchema() }, // foreignBoxReads
145
+ { key: 'fba', valueSchema: new BooleanSchema() }, // familyBoxAccess
142
146
  ])
143
147
  );
144
148
 
@@ -148,6 +152,20 @@ export class AppParams implements Encodable {
148
152
  public localStateSchema: StateSchema;
149
153
  public globalStateSchema: StateSchema;
150
154
  public extraProgramPages: number;
155
+ public version: bigint;
156
+ /**
157
+ * If non-zero, the account that must hold MBR for extra program pages and the
158
+ * global schema.
159
+ */
160
+ public sizeSponsor: Address;
161
+ /**
162
+ * When true, any app may read this app's boxes.
163
+ */
164
+ public foreignBoxReads: boolean;
165
+ /**
166
+ * When true, apps with the same creator may read and write this app's boxes.
167
+ */
168
+ public familyBoxAccess: boolean;
151
169
 
152
170
  constructor(params: {
153
171
  approvalProgram: Uint8Array;
@@ -156,6 +174,10 @@ export class AppParams implements Encodable {
156
174
  localStateSchema: StateSchema;
157
175
  globalStateSchema: StateSchema;
158
176
  extraProgramPages: number;
177
+ version?: bigint;
178
+ sizeSponsor?: Address;
179
+ foreignBoxReads?: boolean;
180
+ familyBoxAccess?: boolean;
159
181
  }) {
160
182
  this.approvalProgram = params.approvalProgram;
161
183
  this.clearStateProgram = params.clearStateProgram;
@@ -163,6 +185,10 @@ export class AppParams implements Encodable {
163
185
  this.localStateSchema = params.localStateSchema;
164
186
  this.globalStateSchema = params.globalStateSchema;
165
187
  this.extraProgramPages = params.extraProgramPages;
188
+ this.version = params.version ?? BigInt(0);
189
+ this.sizeSponsor = params.sizeSponsor ?? Address.zeroAddress();
190
+ this.foreignBoxReads = params.foreignBoxReads ?? false;
191
+ this.familyBoxAccess = params.familyBoxAccess ?? false;
166
192
  }
167
193
 
168
194
  // eslint-disable-next-line class-methods-use-this
@@ -178,6 +204,10 @@ export class AppParams implements Encodable {
178
204
  ['lsch', this.localStateSchema.toEncodingData()],
179
205
  ['gsch', this.globalStateSchema.toEncodingData()],
180
206
  ['epp', this.extraProgramPages],
207
+ ['v', this.version],
208
+ ['ss', this.sizeSponsor],
209
+ ['fbr', this.foreignBoxReads],
210
+ ['fba', this.familyBoxAccess],
181
211
  ]);
182
212
  }
183
213
 
@@ -195,6 +225,10 @@ export class AppParams implements Encodable {
195
225
  localStateSchema: StateSchema.fromEncodingData(data.get('lsch')),
196
226
  globalStateSchema: StateSchema.fromEncodingData(data.get('gsch')),
197
227
  extraProgramPages: Number(data.get('epp')),
228
+ version: data.get('v'),
229
+ sizeSponsor: data.get('ss'),
230
+ foreignBoxReads: data.get('fbr'),
231
+ familyBoxAccess: data.get('fba'),
198
232
  });
199
233
  }
200
234
  }
@@ -592,6 +592,17 @@ export interface HeartbeatTransactionParams {
592
592
  * Must match hbAddress account's current KeyDilution.
593
593
  */
594
594
  keyDilution: bigint;
595
+
596
+ /**
597
+ * Requests the challenge fee discount: when set, the required fee is reduced
598
+ * by one min fee. The network verifies that hbAddress is actually under
599
+ * challenge before granting it, and a heartbeat claiming the discount may not
600
+ * carry any extra fields (note, lease, group, etc.).
601
+ *
602
+ * Only allowed once transaction size pricing is enabled. Before that, the
603
+ * discount was inferred from an underpaid singleton heartbeat instead.
604
+ */
605
+ challengeDiscount?: boolean;
595
606
  }
596
607
 
597
608
  /**
@@ -205,3 +205,16 @@ export function ensureUint64(value: unknown): bigint {
205
205
  }
206
206
  return bigIntValue;
207
207
  }
208
+
209
+ export function isEmptyObject(obj: any) {
210
+ if (!obj || typeof obj !== 'object') return false;
211
+
212
+ for (const key in obj) {
213
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
214
+ if (obj[key] !== undefined) {
215
+ return false;
216
+ }
217
+ }
218
+ }
219
+ return true;
220
+ }