algosdk 2.0.0 → 2.2.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 (175) 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/abi/abi_type.js +6 -5
  5. package/dist/cjs/abi/abi_type.js.map +1 -1
  6. package/dist/cjs/bid.js +6 -5
  7. package/dist/cjs/bid.js.map +1 -1
  8. package/dist/cjs/client/client.js +4 -3
  9. package/dist/cjs/client/client.js.map +1 -1
  10. package/dist/cjs/client/kmd.js +12 -11
  11. package/dist/cjs/client/kmd.js.map +1 -1
  12. package/dist/cjs/client/urlTokenBaseHTTPClient.js +2 -1
  13. package/dist/cjs/client/urlTokenBaseHTTPClient.js.map +1 -1
  14. package/dist/cjs/client/v2/algod/algod.js +32 -0
  15. package/dist/cjs/client/v2/algod/algod.js.map +1 -1
  16. package/dist/cjs/client/v2/algod/compile.js +2 -1
  17. package/dist/cjs/client/v2/algod/compile.js.map +1 -1
  18. package/dist/cjs/client/v2/algod/disassemble.js +46 -0
  19. package/dist/cjs/client/v2/algod/disassemble.js.map +1 -0
  20. package/dist/cjs/client/v2/algod/dryrun.js +2 -1
  21. package/dist/cjs/client/v2/algod/dryrun.js.map +1 -1
  22. package/dist/cjs/client/v2/algod/getApplicationBoxByName.js +2 -1
  23. package/dist/cjs/client/v2/algod/getApplicationBoxByName.js.map +1 -1
  24. package/dist/cjs/client/v2/algod/models/types.js +141 -21
  25. package/dist/cjs/client/v2/algod/models/types.js.map +1 -1
  26. package/dist/cjs/client/v2/algod/sendRawTransaction.js +2 -1
  27. package/dist/cjs/client/v2/algod/sendRawTransaction.js.map +1 -1
  28. package/dist/cjs/client/v2/algod/simulateTransaction.js +88 -0
  29. package/dist/cjs/client/v2/algod/simulateTransaction.js.map +1 -0
  30. package/dist/cjs/client/v2/basemodel.js +3 -2
  31. package/dist/cjs/client/v2/basemodel.js.map +1 -1
  32. package/dist/cjs/client/v2/indexer/lookupAccountTransactions.js +2 -1
  33. package/dist/cjs/client/v2/indexer/lookupAccountTransactions.js.map +1 -1
  34. package/dist/cjs/client/v2/indexer/lookupApplicationBoxByIDandName.js +2 -1
  35. package/dist/cjs/client/v2/indexer/lookupApplicationBoxByIDandName.js.map +1 -1
  36. package/dist/cjs/client/v2/indexer/models/types.js +39 -38
  37. package/dist/cjs/client/v2/indexer/models/types.js.map +1 -1
  38. package/dist/cjs/composer.js +75 -23
  39. package/dist/cjs/composer.js.map +1 -1
  40. package/dist/cjs/dryrun.js +6 -5
  41. package/dist/cjs/dryrun.js.map +1 -1
  42. package/dist/cjs/encoding/address.js +2 -1
  43. package/dist/cjs/encoding/address.js.map +1 -1
  44. package/dist/cjs/encoding/bigint.js +2 -1
  45. package/dist/cjs/encoding/bigint.js.map +1 -1
  46. package/dist/cjs/encoding/encoding.js +14 -3
  47. package/dist/cjs/encoding/encoding.js.map +1 -1
  48. package/dist/cjs/encoding/uint64.js +14 -8
  49. package/dist/cjs/encoding/uint64.js.map +1 -1
  50. package/dist/cjs/group.js +6 -5
  51. package/dist/cjs/group.js.map +1 -1
  52. package/dist/cjs/logicsig.js +22 -8
  53. package/dist/cjs/logicsig.js.map +1 -1
  54. package/dist/cjs/main.js +7 -5
  55. package/dist/cjs/main.js.map +1 -1
  56. package/dist/cjs/multisig.js +6 -5
  57. package/dist/cjs/multisig.js.map +1 -1
  58. package/dist/cjs/signer.js +17 -1
  59. package/dist/cjs/signer.js.map +1 -1
  60. package/dist/cjs/transaction.js +81 -64
  61. package/dist/cjs/transaction.js.map +1 -1
  62. package/dist/cjs/types/transactions/encoded.js +0 -3
  63. package/dist/cjs/types/transactions/encoded.js.map +1 -1
  64. package/dist/cjs/utils/utils.js +5 -1
  65. package/dist/cjs/utils/utils.js.map +1 -1
  66. package/dist/esm/abi/abi_type.js +1 -0
  67. package/dist/esm/abi/abi_type.js.map +1 -1
  68. package/dist/esm/bid.js +1 -0
  69. package/dist/esm/bid.js.map +1 -1
  70. package/dist/esm/client/client.js +1 -0
  71. package/dist/esm/client/client.js.map +1 -1
  72. package/dist/esm/client/kmd.js +1 -0
  73. package/dist/esm/client/kmd.js.map +1 -1
  74. package/dist/esm/client/urlTokenBaseHTTPClient.js +1 -0
  75. package/dist/esm/client/urlTokenBaseHTTPClient.js.map +1 -1
  76. package/dist/esm/client/v2/algod/algod.js +32 -0
  77. package/dist/esm/client/v2/algod/algod.js.map +1 -1
  78. package/dist/esm/client/v2/algod/compile.js +1 -0
  79. package/dist/esm/client/v2/algod/compile.js.map +1 -1
  80. package/dist/esm/client/v2/algod/disassemble.js +38 -0
  81. package/dist/esm/client/v2/algod/disassemble.js.map +1 -0
  82. package/dist/esm/client/v2/algod/dryrun.js +1 -0
  83. package/dist/esm/client/v2/algod/dryrun.js.map +1 -1
  84. package/dist/esm/client/v2/algod/getApplicationBoxByName.js +1 -0
  85. package/dist/esm/client/v2/algod/getApplicationBoxByName.js.map +1 -1
  86. package/dist/esm/client/v2/algod/models/types.js +117 -0
  87. package/dist/esm/client/v2/algod/models/types.js.map +1 -1
  88. package/dist/esm/client/v2/algod/sendRawTransaction.js +1 -0
  89. package/dist/esm/client/v2/algod/sendRawTransaction.js.map +1 -1
  90. package/dist/esm/client/v2/algod/simulateTransaction.js +57 -0
  91. package/dist/esm/client/v2/algod/simulateTransaction.js.map +1 -0
  92. package/dist/esm/client/v2/basemodel.js +1 -0
  93. package/dist/esm/client/v2/basemodel.js.map +1 -1
  94. package/dist/esm/client/v2/indexer/lookupAccountTransactions.js +1 -0
  95. package/dist/esm/client/v2/indexer/lookupAccountTransactions.js.map +1 -1
  96. package/dist/esm/client/v2/indexer/lookupApplicationBoxByIDandName.js +1 -0
  97. package/dist/esm/client/v2/indexer/lookupApplicationBoxByIDandName.js.map +1 -1
  98. package/dist/esm/client/v2/indexer/models/types.js +1 -0
  99. package/dist/esm/client/v2/indexer/models/types.js.map +1 -1
  100. package/dist/esm/composer.js +75 -23
  101. package/dist/esm/composer.js.map +1 -1
  102. package/dist/esm/dryrun.js +1 -0
  103. package/dist/esm/dryrun.js.map +1 -1
  104. package/dist/esm/encoding/address.js +1 -0
  105. package/dist/esm/encoding/address.js.map +1 -1
  106. package/dist/esm/encoding/bigint.js +1 -0
  107. package/dist/esm/encoding/bigint.js.map +1 -1
  108. package/dist/esm/encoding/encoding.js +12 -2
  109. package/dist/esm/encoding/encoding.js.map +1 -1
  110. package/dist/esm/encoding/uint64.js +14 -8
  111. package/dist/esm/encoding/uint64.js.map +1 -1
  112. package/dist/esm/group.js +1 -0
  113. package/dist/esm/group.js.map +1 -1
  114. package/dist/esm/logicsig.js +13 -0
  115. package/dist/esm/logicsig.js.map +1 -1
  116. package/dist/esm/main.js +2 -1
  117. package/dist/esm/main.js.map +1 -1
  118. package/dist/esm/multisig.js +1 -0
  119. package/dist/esm/multisig.js.map +1 -1
  120. package/dist/esm/signer.js +15 -0
  121. package/dist/esm/signer.js.map +1 -1
  122. package/dist/esm/transaction.js +16 -0
  123. package/dist/esm/transaction.js.map +1 -1
  124. package/dist/esm/types/transactions/encoded.js +0 -3
  125. package/dist/esm/types/transactions/encoded.js.map +1 -1
  126. package/dist/esm/utils/utils.js +5 -1
  127. package/dist/esm/utils/utils.js.map +1 -1
  128. package/dist/types/client/v2/algod/algod.d.ts +28 -0
  129. package/dist/types/client/v2/algod/disassemble.d.ts +20 -0
  130. package/dist/types/client/v2/algod/models/types.d.ts +103 -0
  131. package/dist/types/client/v2/algod/simulateTransaction.d.ts +19 -0
  132. package/dist/types/client/v2/basemodel.d.ts +0 -3
  133. package/dist/types/composer.d.ts +35 -2
  134. package/dist/types/encoding/encoding.d.ts +7 -0
  135. package/dist/types/logicsig.d.ts +8 -0
  136. package/dist/types/main.d.ts +1 -1
  137. package/dist/types/signer.d.ts +5 -0
  138. package/dist/types/transaction.d.ts +9 -0
  139. package/dist/types/types/transactions/builder.d.ts +1 -1
  140. package/dist/types/types/transactions/encoded.d.ts +1 -1
  141. package/dist/types/types/utils.d.ts +1 -1
  142. package/package.json +2 -3
  143. package/src/abi/abi_type.ts +1 -0
  144. package/src/bid.ts +1 -0
  145. package/src/client/client.ts +1 -0
  146. package/src/client/kmd.ts +1 -0
  147. package/src/client/urlTokenBaseHTTPClient.ts +1 -0
  148. package/src/client/v2/algod/algod.ts +34 -0
  149. package/src/client/v2/algod/compile.ts +1 -0
  150. package/src/client/v2/algod/disassemble.ts +46 -0
  151. package/src/client/v2/algod/dryrun.ts +1 -0
  152. package/src/client/v2/algod/getApplicationBoxByName.ts +1 -0
  153. package/src/client/v2/algod/models/types.ts +223 -0
  154. package/src/client/v2/algod/sendRawTransaction.ts +1 -0
  155. package/src/client/v2/algod/simulateTransaction.ts +74 -0
  156. package/src/client/v2/basemodel.ts +2 -0
  157. package/src/client/v2/indexer/lookupAccountTransactions.ts +1 -0
  158. package/src/client/v2/indexer/lookupApplicationBoxByIDandName.ts +1 -0
  159. package/src/client/v2/indexer/models/types.ts +1 -0
  160. package/src/composer.ts +130 -34
  161. package/src/dryrun.ts +1 -0
  162. package/src/encoding/address.ts +1 -0
  163. package/src/encoding/bigint.ts +2 -0
  164. package/src/encoding/encoding.ts +13 -2
  165. package/src/encoding/uint64.ts +16 -10
  166. package/src/group.ts +1 -0
  167. package/src/logicsig.ts +24 -0
  168. package/src/main.ts +2 -0
  169. package/src/multisig.ts +1 -0
  170. package/src/signer.ts +18 -1
  171. package/src/transaction.ts +19 -0
  172. package/src/types/transactions/builder.ts +4 -4
  173. package/src/types/transactions/encoded.ts +2 -0
  174. package/src/types/utils.ts +1 -1
  175. package/src/utils/utils.ts +3 -0
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  /* eslint-disable no-use-before-define */
6
+ import { Buffer } from 'buffer';
6
7
  import BaseModel from '../../basemodel';
7
8
  import { EncodedSignedTransaction } from '../../../../types/transactions/encoded';
8
9
  import BlockHeader from '../../../../types/blockHeader';
@@ -3083,6 +3084,228 @@ export class PostTransactionsResponse extends BaseModel {
3083
3084
  }
3084
3085
  }
3085
3086
 
3087
+ /**
3088
+ * Result of a transaction group simulation.
3089
+ */
3090
+ export class SimulateResponse extends BaseModel {
3091
+ /**
3092
+ * The round immediately preceding this simulation. State changes through this
3093
+ * round were used to run this simulation.
3094
+ */
3095
+ public lastRound: number | bigint;
3096
+
3097
+ /**
3098
+ * A result object for each transaction group that was simulated.
3099
+ */
3100
+ public txnGroups: SimulateTransactionGroupResult[];
3101
+
3102
+ /**
3103
+ * The version of this response object.
3104
+ */
3105
+ public version: number | bigint;
3106
+
3107
+ /**
3108
+ * Indicates whether the simulated transactions would have succeeded during an
3109
+ * actual submission. If any transaction fails or is missing a signature, this will
3110
+ * be false.
3111
+ */
3112
+ public wouldSucceed: boolean;
3113
+
3114
+ /**
3115
+ * Creates a new `SimulateResponse` object.
3116
+ * @param lastRound - The round immediately preceding this simulation. State changes through this
3117
+ * round were used to run this simulation.
3118
+ * @param txnGroups - A result object for each transaction group that was simulated.
3119
+ * @param version - The version of this response object.
3120
+ * @param wouldSucceed - Indicates whether the simulated transactions would have succeeded during an
3121
+ * actual submission. If any transaction fails or is missing a signature, this will
3122
+ * be false.
3123
+ */
3124
+ constructor({
3125
+ lastRound,
3126
+ txnGroups,
3127
+ version,
3128
+ wouldSucceed,
3129
+ }: {
3130
+ lastRound: number | bigint;
3131
+ txnGroups: SimulateTransactionGroupResult[];
3132
+ version: number | bigint;
3133
+ wouldSucceed: boolean;
3134
+ }) {
3135
+ super();
3136
+ this.lastRound = lastRound;
3137
+ this.txnGroups = txnGroups;
3138
+ this.version = version;
3139
+ this.wouldSucceed = wouldSucceed;
3140
+
3141
+ this.attribute_map = {
3142
+ lastRound: 'last-round',
3143
+ txnGroups: 'txn-groups',
3144
+ version: 'version',
3145
+ wouldSucceed: 'would-succeed',
3146
+ };
3147
+ }
3148
+
3149
+ // eslint-disable-next-line camelcase
3150
+ static from_obj_for_encoding(data: Record<string, any>): SimulateResponse {
3151
+ /* eslint-disable dot-notation */
3152
+ if (typeof data['last-round'] === 'undefined')
3153
+ throw new Error(
3154
+ `Response is missing required field 'last-round': ${data}`
3155
+ );
3156
+ if (!Array.isArray(data['txn-groups']))
3157
+ throw new Error(
3158
+ `Response is missing required array field 'txn-groups': ${data}`
3159
+ );
3160
+ if (typeof data['version'] === 'undefined')
3161
+ throw new Error(`Response is missing required field 'version': ${data}`);
3162
+ if (typeof data['would-succeed'] === 'undefined')
3163
+ throw new Error(
3164
+ `Response is missing required field 'would-succeed': ${data}`
3165
+ );
3166
+ return new SimulateResponse({
3167
+ lastRound: data['last-round'],
3168
+ txnGroups: data['txn-groups'].map(
3169
+ SimulateTransactionGroupResult.from_obj_for_encoding
3170
+ ),
3171
+ version: data['version'],
3172
+ wouldSucceed: data['would-succeed'],
3173
+ });
3174
+ /* eslint-enable dot-notation */
3175
+ }
3176
+ }
3177
+
3178
+ /**
3179
+ * Simulation result for an atomic transaction group
3180
+ */
3181
+ export class SimulateTransactionGroupResult extends BaseModel {
3182
+ /**
3183
+ * Simulation result for individual transactions
3184
+ */
3185
+ public txnResults: SimulateTransactionResult[];
3186
+
3187
+ /**
3188
+ * If present, indicates which transaction in this group caused the failure. This
3189
+ * array represents the path to the failing transaction. Indexes are zero based,
3190
+ * the first element indicates the top-level transaction, and successive elements
3191
+ * indicate deeper inner transactions.
3192
+ */
3193
+ public failedAt?: (number | bigint)[];
3194
+
3195
+ /**
3196
+ * If present, indicates that the transaction group failed and specifies why that
3197
+ * happened
3198
+ */
3199
+ public failureMessage?: string;
3200
+
3201
+ /**
3202
+ * Creates a new `SimulateTransactionGroupResult` object.
3203
+ * @param txnResults - Simulation result for individual transactions
3204
+ * @param failedAt - If present, indicates which transaction in this group caused the failure. This
3205
+ * array represents the path to the failing transaction. Indexes are zero based,
3206
+ * the first element indicates the top-level transaction, and successive elements
3207
+ * indicate deeper inner transactions.
3208
+ * @param failureMessage - If present, indicates that the transaction group failed and specifies why that
3209
+ * happened
3210
+ */
3211
+ constructor({
3212
+ txnResults,
3213
+ failedAt,
3214
+ failureMessage,
3215
+ }: {
3216
+ txnResults: SimulateTransactionResult[];
3217
+ failedAt?: (number | bigint)[];
3218
+ failureMessage?: string;
3219
+ }) {
3220
+ super();
3221
+ this.txnResults = txnResults;
3222
+ this.failedAt = failedAt;
3223
+ this.failureMessage = failureMessage;
3224
+
3225
+ this.attribute_map = {
3226
+ txnResults: 'txn-results',
3227
+ failedAt: 'failed-at',
3228
+ failureMessage: 'failure-message',
3229
+ };
3230
+ }
3231
+
3232
+ // eslint-disable-next-line camelcase
3233
+ static from_obj_for_encoding(
3234
+ data: Record<string, any>
3235
+ ): SimulateTransactionGroupResult {
3236
+ /* eslint-disable dot-notation */
3237
+ if (!Array.isArray(data['txn-results']))
3238
+ throw new Error(
3239
+ `Response is missing required array field 'txn-results': ${data}`
3240
+ );
3241
+ return new SimulateTransactionGroupResult({
3242
+ txnResults: data['txn-results'].map(
3243
+ SimulateTransactionResult.from_obj_for_encoding
3244
+ ),
3245
+ failedAt: data['failed-at'],
3246
+ failureMessage: data['failure-message'],
3247
+ });
3248
+ /* eslint-enable dot-notation */
3249
+ }
3250
+ }
3251
+
3252
+ /**
3253
+ * Simulation result for an individual transaction
3254
+ */
3255
+ export class SimulateTransactionResult extends BaseModel {
3256
+ /**
3257
+ * Details about a pending transaction. If the transaction was recently confirmed,
3258
+ * includes confirmation details like the round and reward details.
3259
+ */
3260
+ public txnResult: PendingTransactionResponse;
3261
+
3262
+ /**
3263
+ * A boolean indicating whether this transaction is missing signatures
3264
+ */
3265
+ public missingSignature?: boolean;
3266
+
3267
+ /**
3268
+ * Creates a new `SimulateTransactionResult` object.
3269
+ * @param txnResult - Details about a pending transaction. If the transaction was recently confirmed,
3270
+ * includes confirmation details like the round and reward details.
3271
+ * @param missingSignature - A boolean indicating whether this transaction is missing signatures
3272
+ */
3273
+ constructor({
3274
+ txnResult,
3275
+ missingSignature,
3276
+ }: {
3277
+ txnResult: PendingTransactionResponse;
3278
+ missingSignature?: boolean;
3279
+ }) {
3280
+ super();
3281
+ this.txnResult = txnResult;
3282
+ this.missingSignature = missingSignature;
3283
+
3284
+ this.attribute_map = {
3285
+ txnResult: 'txn-result',
3286
+ missingSignature: 'missing-signature',
3287
+ };
3288
+ }
3289
+
3290
+ // eslint-disable-next-line camelcase
3291
+ static from_obj_for_encoding(
3292
+ data: Record<string, any>
3293
+ ): SimulateTransactionResult {
3294
+ /* eslint-disable dot-notation */
3295
+ if (typeof data['txn-result'] === 'undefined')
3296
+ throw new Error(
3297
+ `Response is missing required field 'txn-result': ${data}`
3298
+ );
3299
+ return new SimulateTransactionResult({
3300
+ txnResult: PendingTransactionResponse.from_obj_for_encoding(
3301
+ data['txn-result']
3302
+ ),
3303
+ missingSignature: data['missing-signature'],
3304
+ });
3305
+ /* eslint-enable dot-notation */
3306
+ }
3307
+ }
3308
+
3086
3309
  /**
3087
3310
  * Represents a state proof and its corresponding message
3088
3311
  */
@@ -1,3 +1,4 @@
1
+ import { Buffer } from 'buffer';
1
2
  import JSONRequest from '../jsonrequest';
2
3
  import HTTPClient from '../../client';
3
4
  import { concatArrays } from '../../../utils/utils';
@@ -0,0 +1,74 @@
1
+ import { Buffer } from 'buffer';
2
+ import * as encoding from '../../../encoding/encoding';
3
+ import { concatArrays } from '../../../utils/utils';
4
+ import HTTPClient from '../../client';
5
+ import JSONRequest from '../jsonrequest';
6
+ import { SimulateResponse } from './models/types';
7
+
8
+ /**
9
+ * Sets the default header (if not previously set) for simulating a raw
10
+ * transaction.
11
+ * @param headers - A headers object
12
+ */
13
+ export function setSimulateTransactionsHeaders(headers = {}) {
14
+ let hdrs = headers;
15
+ if (Object.keys(hdrs).every((key) => key.toLowerCase() !== 'content-type')) {
16
+ hdrs = { ...headers };
17
+ hdrs['Content-Type'] = 'application/x-binary';
18
+ }
19
+ return hdrs;
20
+ }
21
+
22
+ function isByteArray(array: any): array is Uint8Array {
23
+ return array && array.byteLength !== undefined;
24
+ }
25
+
26
+ /**
27
+ * Simulates signed txns.
28
+ */
29
+ export default class SimulateRawTransactions extends JSONRequest<
30
+ SimulateResponse,
31
+ Uint8Array
32
+ > {
33
+ private txnBytesToPost: Uint8Array;
34
+
35
+ constructor(c: HTTPClient, stxOrStxs: Uint8Array | Uint8Array[]) {
36
+ super(c);
37
+ this.query.format = 'msgpack';
38
+
39
+ let forPosting = stxOrStxs;
40
+ if (Array.isArray(stxOrStxs)) {
41
+ if (!stxOrStxs.every(isByteArray)) {
42
+ throw new TypeError('Array elements must be byte arrays');
43
+ }
44
+ // Flatten into a single Uint8Array
45
+ forPosting = concatArrays(...stxOrStxs);
46
+ } else if (!isByteArray(forPosting)) {
47
+ throw new TypeError('Argument must be byte array');
48
+ }
49
+ this.txnBytesToPost = forPosting;
50
+ }
51
+
52
+ // eslint-disable-next-line class-methods-use-this
53
+ path() {
54
+ return '/v2/transactions/simulate';
55
+ }
56
+
57
+ async do(headers = {}) {
58
+ const txHeaders = setSimulateTransactionsHeaders(headers);
59
+ const res = await this.c.post(
60
+ this.path(),
61
+ Buffer.from(this.txnBytesToPost),
62
+ txHeaders,
63
+ this.query,
64
+ false
65
+ );
66
+ return this.prepare(res.body);
67
+ }
68
+
69
+ // eslint-disable-next-line class-methods-use-this
70
+ prepare(body: Uint8Array): SimulateResponse {
71
+ const decoded = encoding.decode(body);
72
+ return SimulateResponse.from_obj_for_encoding(decoded);
73
+ }
74
+ }
@@ -1,3 +1,5 @@
1
+ import { Buffer } from 'buffer';
2
+
1
3
  /**
2
4
  * Base class for models
3
5
  */
@@ -1,3 +1,4 @@
1
+ import { Buffer } from 'buffer';
1
2
  import JSONRequest from '../jsonrequest';
2
3
  import HTTPClient from '../../client';
3
4
  import IntDecoding from '../../../types/intDecoding';
@@ -1,3 +1,4 @@
1
+ import { Buffer } from 'buffer';
1
2
  import JSONRequest from '../jsonrequest';
2
3
  import HTTPClient from '../../client';
3
4
  import IntDecoding from '../../../types/intDecoding';
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  /* eslint-disable no-use-before-define */
6
+ import { Buffer } from 'buffer';
6
7
  import BaseModel from '../../basemodel';
7
8
 
8
9
  /**
package/src/composer.ts CHANGED
@@ -1,30 +1,32 @@
1
+ import { Buffer } from 'buffer';
1
2
  import {
2
- ABIType,
3
- ABITupleType,
4
- ABIUintType,
5
3
  ABIAddressType,
6
- ABIValue,
4
+ abiCheckTransactionType,
7
5
  ABIMethod,
8
6
  ABIReferenceType,
9
- abiTypeIsTransaction,
10
- abiCheckTransactionType,
7
+ ABITupleType,
8
+ ABIType,
11
9
  abiTypeIsReference,
10
+ abiTypeIsTransaction,
11
+ ABIUintType,
12
+ ABIValue,
12
13
  } from './abi';
13
- import { Transaction, decodeSignedTransaction } from './transaction';
14
- import { makeApplicationCallTxnFromObject } from './makeTxn';
15
- import { assignGroupID } from './group';
16
- import { waitForConfirmation } from './wait';
17
14
  import Algodv2 from './client/v2/algod/algod';
15
+ import { SimulateResponse } from './client/v2/algod/models/types';
16
+ import { assignGroupID } from './group';
17
+ import { makeApplicationCallTxnFromObject } from './makeTxn';
18
18
  import {
19
+ isTransactionWithSigner,
19
20
  TransactionSigner,
20
21
  TransactionWithSigner,
21
- isTransactionWithSigner,
22
22
  } from './signer';
23
+ import { decodeSignedTransaction, Transaction } from './transaction';
23
24
  import {
24
25
  BoxReference,
25
26
  OnApplicationComplete,
26
27
  SuggestedParams,
27
28
  } from './types/transactions/base';
29
+ import { waitForConfirmation } from './wait';
28
30
 
29
31
  // First 4 bytes of SHA-512/256 hash of "return"
30
32
  const RETURN_PREFIX = Buffer.from([21, 31, 124, 117]);
@@ -202,6 +204,9 @@ export class AtomicTransactionComposer {
202
204
  numLocalInts,
203
205
  numLocalByteSlices,
204
206
  extraPages,
207
+ appAccounts,
208
+ appForeignApps,
209
+ appForeignAssets,
205
210
  boxes,
206
211
  note,
207
212
  lease,
@@ -234,6 +239,12 @@ export class AtomicTransactionComposer {
234
239
  numLocalByteSlices?: number;
235
240
  /** The number of extra pages to allocate for the application's programs. Only set this if this is an application creation call. If omitted, defaults to 0. */
236
241
  extraPages?: number;
242
+ /** Array of Address strings that represent external accounts supplied to this application. If accounts are provided here, the accounts specified in the method args will appear after these. */
243
+ appAccounts?: string[];
244
+ /** Array of App ID numbers that represent external apps supplied to this application. If apps are provided here, the apps specified in the method args will appear after these. */
245
+ appForeignApps?: number[];
246
+ /** Array of Asset ID numbers that represent external assets supplied to this application. If assets are provided here, the assets specified in the method args will appear after these. */
247
+ appForeignAssets?: number[];
237
248
  /** The box references for this application call */
238
249
  boxes?: BoxReference[];
239
250
  /** The note value for this application call */
@@ -370,9 +381,12 @@ export class AtomicTransactionComposer {
370
381
  }
371
382
 
372
383
  const resolvedRefIndexes: number[] = [];
373
- const foreignAccounts: string[] = [];
374
- const foreignApps: number[] = [];
375
- const foreignAssets: number[] = [];
384
+ const foreignAccounts: string[] =
385
+ appAccounts == null ? [] : appAccounts.slice();
386
+ const foreignApps: number[] =
387
+ appForeignApps == null ? [] : appForeignApps.slice();
388
+ const foreignAssets: number[] =
389
+ appForeignAssets == null ? [] : appForeignAssets.slice();
376
390
  for (let i = 0; i < refArgTypes.length; i++) {
377
391
  const refType = refArgTypes[i];
378
392
  const refValue = refArgValues[i];
@@ -587,6 +601,60 @@ export class AtomicTransactionComposer {
587
601
  return this.txIDs;
588
602
  }
589
603
 
604
+ /**
605
+ * Simulates the transaction group in the network.
606
+ *
607
+ * The composer will try to sign any transactions in the group, then simulate
608
+ * the results.
609
+ * Simulating the group will not change the composer's status.
610
+ *
611
+ * @param client - An Algodv2 client
612
+ *
613
+ * @returns A promise that, upon success, resolves to an object containing an
614
+ * array of results containing one element for each method call transaction
615
+ * in this group (ABIResult[]) and the SimulateResponse object.
616
+ */
617
+ async simulate(
618
+ client: Algodv2
619
+ ): Promise<{
620
+ methodResults: ABIResult[];
621
+ simulateResponse: SimulateResponse;
622
+ }> {
623
+ if (this.status > AtomicTransactionComposerStatus.SUBMITTED) {
624
+ throw new Error(
625
+ 'Simulated Transaction group has already been submitted to the network'
626
+ );
627
+ }
628
+
629
+ const stxns = await this.gatherSignatures();
630
+
631
+ const simulateResponse = await client.simulateRawTransactions(stxns).do();
632
+
633
+ // Parse method response
634
+ const methodResults: ABIResult[] = [];
635
+ for (const [txnIndex, method] of this.methodCalls) {
636
+ const txID = this.txIDs[txnIndex];
637
+ const pendingInfo =
638
+ simulateResponse.txnGroups[0].txnResults[txnIndex].txnResult;
639
+
640
+ const methodResult: ABIResult = {
641
+ txID,
642
+ rawReturnValue: new Uint8Array(),
643
+ method,
644
+ };
645
+
646
+ methodResults.push(
647
+ AtomicTransactionComposer.parseMethodResponse(
648
+ method,
649
+ methodResult,
650
+ pendingInfo.get_obj_for_encoding()
651
+ )
652
+ );
653
+ }
654
+
655
+ return { methodResults, simulateResponse };
656
+ }
657
+
590
658
  /**
591
659
  * Send the transaction group to the network and wait until it's committed to a block. An error
592
660
  * will be thrown if submission or execution fails.
@@ -640,7 +708,7 @@ export class AtomicTransactionComposer {
640
708
  for (const [txnIndex, method] of this.methodCalls) {
641
709
  const txID = txIDs[txnIndex];
642
710
 
643
- const methodResult: ABIResult = {
711
+ let methodResult: ABIResult = {
644
712
  txID,
645
713
  rawReturnValue: new Uint8Array(),
646
714
  method,
@@ -652,26 +720,12 @@ export class AtomicTransactionComposer {
652
720
  ? confirmedTxnInfo
653
721
  : // eslint-disable-next-line no-await-in-loop
654
722
  await client.pendingTransactionInformation(txID).do();
655
- methodResult.txInfo = pendingInfo;
656
- if (method.returns.type !== 'void') {
657
- const logs: string[] = pendingInfo.logs || [];
658
- if (logs.length === 0) {
659
- throw new Error('App call transaction did not log a return value');
660
- }
661
-
662
- const lastLog = Buffer.from(logs[logs.length - 1], 'base64');
663
- if (
664
- lastLog.byteLength < 4 ||
665
- !lastLog.slice(0, 4).equals(RETURN_PREFIX)
666
- ) {
667
- throw new Error('App call transaction did not log a return value');
668
- }
669
723
 
670
- methodResult.rawReturnValue = new Uint8Array(lastLog.slice(4));
671
- methodResult.returnValue = method.returns.type.decode(
672
- methodResult.rawReturnValue
673
- );
674
- }
724
+ methodResult = AtomicTransactionComposer.parseMethodResponse(
725
+ method,
726
+ methodResult,
727
+ pendingInfo
728
+ );
675
729
  } catch (err) {
676
730
  methodResult.decodeError = err;
677
731
  }
@@ -685,4 +739,46 @@ export class AtomicTransactionComposer {
685
739
  methodResults,
686
740
  };
687
741
  }
742
+
743
+ /**
744
+ * Parses a single ABI Method transaction log into a ABI result object.
745
+ *
746
+ * @param method
747
+ * @param methodResult
748
+ * @param pendingInfo
749
+ * @returns An ABIResult object
750
+ */
751
+ static parseMethodResponse(
752
+ method: ABIMethod,
753
+ methodResult: ABIResult,
754
+ pendingInfo: Record<string, any>
755
+ ): ABIResult {
756
+ const returnedResult: ABIResult = methodResult;
757
+ try {
758
+ returnedResult.txInfo = pendingInfo;
759
+ if (method.returns.type !== 'void') {
760
+ const logs: string[] = pendingInfo.logs || [];
761
+ if (logs.length === 0) {
762
+ throw new Error('App call transaction did not log a return value');
763
+ }
764
+
765
+ const lastLog = Buffer.from(logs[logs.length - 1], 'base64');
766
+ if (
767
+ lastLog.byteLength < 4 ||
768
+ !lastLog.slice(0, 4).equals(RETURN_PREFIX)
769
+ ) {
770
+ throw new Error('App call transaction did not log a return value');
771
+ }
772
+
773
+ returnedResult.rawReturnValue = new Uint8Array(lastLog.slice(4));
774
+ returnedResult.returnValue = method.returns.type.decode(
775
+ methodResult.rawReturnValue
776
+ );
777
+ }
778
+ } catch (err) {
779
+ returnedResult.decodeError = err;
780
+ }
781
+
782
+ return returnedResult;
783
+ }
688
784
  }
package/src/dryrun.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Buffer } from 'buffer';
1
2
  import AlgodClient from './client/v2/algod/algod';
2
3
  import {
3
4
  AccountStateDelta,
@@ -1,3 +1,4 @@
1
+ import { Buffer } from 'buffer';
1
2
  import base32 from 'hi-base32';
2
3
  import * as nacl from '../nacl/naclWrappers';
3
4
  import * as utils from '../utils/utils';
@@ -1,3 +1,5 @@
1
+ import { Buffer } from 'buffer';
2
+
1
3
  /**
2
4
  * bigIntToBytes converts a BigInt to a big-endian Uint8Array for encoding.
3
5
  * @param bi - The bigint to convert.
@@ -33,6 +33,18 @@ function containsEmpty(obj: Record<string | number | symbol, any>) {
33
33
  return { containsEmpty: false, firstEmptyKey: undefined };
34
34
  }
35
35
 
36
+ /**
37
+ * rawEncode encodes objects using msgpack, regardless of whether there are
38
+ * empty or 0 value fields.
39
+ * @param obj - a dictionary to be encoded. May or may not contain empty or 0 values.
40
+ * @returns msgpack representation of the object
41
+ */
42
+ export function rawEncode(obj: Record<string | number | symbol, any>) {
43
+ // enable the canonical option
44
+ const options = { sortKeys: true };
45
+ return msgpack.encode(obj, options);
46
+ }
47
+
36
48
  /**
37
49
  * encode encodes objects using msgpack
38
50
  * @param obj - a dictionary to be encoded. Must not contain empty or 0 values.
@@ -47,8 +59,7 @@ export function encode(obj: Record<string | number | symbol, any>) {
47
59
  }
48
60
 
49
61
  // enable the canonical option
50
- const options = { sortKeys: true };
51
- return msgpack.encode(obj, options);
62
+ return rawEncode(obj);
52
63
  }
53
64
 
54
65
  export function decode(buffer: ArrayLike<number>) {
@@ -1,3 +1,10 @@
1
+ import { concatArrays } from '../utils/utils';
2
+
3
+ // NOTE: at the moment we specifically do not use Buffer.writeBigUInt64BE and
4
+ // Buffer.readBigUInt64BE. This is because projects using webpack v4
5
+ // automatically include an old version of the npm `buffer` package (v4.9.2 at
6
+ // the time of writing), and this old version does not have these methods.
7
+
1
8
  /**
2
9
  * encodeUint64 converts an integer to its binary representation.
3
10
  * @param num - The number to convert. This must be an unsigned integer less than
@@ -12,11 +19,11 @@ export function encodeUint64(num: number | bigint) {
12
19
  throw new Error('Input is not a 64-bit unsigned integer');
13
20
  }
14
21
 
15
- const buf = Buffer.allocUnsafe(8);
22
+ const encoding = new Uint8Array(8);
23
+ const view = new DataView(encoding.buffer);
24
+ view.setBigUint64(0, BigInt(num));
16
25
 
17
- buf.writeBigUInt64BE(BigInt(num));
18
-
19
- return new Uint8Array(buf);
26
+ return encoding;
20
27
  }
21
28
 
22
29
  /**
@@ -59,13 +66,12 @@ export function decodeUint64(data: any, decodingMode: any = 'safe') {
59
66
  }
60
67
 
61
68
  // insert 0s at the beginning if data is smaller than 8 bytes
62
- const padding = Buffer.allocUnsafe(8 - data.byteLength);
63
- padding.fill(0);
64
-
65
- const buf = Buffer.concat([padding, Buffer.from(data)]);
69
+ const padding = new Uint8Array(8 - data.byteLength);
70
+ const encoding = concatArrays(padding, data);
71
+ const view = new DataView(encoding.buffer);
66
72
 
67
- const num = buf.readBigUInt64BE();
68
- const isBig = num > Number.MAX_SAFE_INTEGER;
73
+ const num = view.getBigUint64(0);
74
+ const isBig = num > BigInt(Number.MAX_SAFE_INTEGER);
69
75
 
70
76
  if (decodingMode === 'safe') {
71
77
  if (isBig) {
package/src/group.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Buffer } from 'buffer';
1
2
  import * as txnBuilder from './transaction';
2
3
  import * as nacl from './nacl/naclWrappers';
3
4
  import * as encoding from './encoding/encoding';