@usearete/sdk 0.10.0 → 0.12.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.
package/README.md CHANGED
@@ -348,6 +348,7 @@ Available reads include:
348
348
  - `minimumBalanceForRentExemption(space)`
349
349
  - `clock()`
350
350
  - `account(address)`
351
+ - `accounts(addresses)` - batched `account(address)`, up to 100 per call, results aligned with the input order
351
352
  - `mint(address)`
352
353
  - `tokenAccount(address)`
353
354
  - `balance({ owner, mint, tokenProgram? })`
package/dist/index.cjs CHANGED
@@ -3123,6 +3123,30 @@ function createTypedViews(stack, storage, subscriptionRegistry) {
3123
3123
  return views;
3124
3124
  }
3125
3125
 
3126
+ /**
3127
+ * Non-enumerable brand attached by the operation and read factories so
3128
+ * tooling (e.g. the knowledge-layer extractor's runtime walk) can classify
3129
+ * values by brand instead of duck-typing. Non-enumerable keeps JSON
3130
+ * serialization and object spreads of surrounding containers unchanged.
3131
+ */
3132
+ const OPERATION_KIND = '__areteOperationKind';
3133
+ function brandOperationKind(value, kind) {
3134
+ Object.defineProperty(value, OPERATION_KIND, {
3135
+ value: kind,
3136
+ enumerable: false,
3137
+ writable: false,
3138
+ configurable: false,
3139
+ });
3140
+ return value;
3141
+ }
3142
+ function getOperationKind(value) {
3143
+ if (value === null || (typeof value !== 'object' && typeof value !== 'function')) {
3144
+ return undefined;
3145
+ }
3146
+ const kind = value[OPERATION_KIND];
3147
+ return typeof kind === 'string' ? kind : undefined;
3148
+ }
3149
+
3126
3150
  class ReadRequestError extends Error {
3127
3151
  constructor(input) {
3128
3152
  super(`Read request to '${input.path}' failed (${input.status}): ${input.body}`);
@@ -3159,26 +3183,26 @@ async function parseReadResponse(response, path) {
3159
3183
  return response.json();
3160
3184
  }
3161
3185
  function programAccountRead(input) {
3162
- return {
3186
+ return brandOperationKind({
3163
3187
  account: input.account,
3164
3188
  schema: input.schema,
3165
- };
3189
+ }, 'account-fetch');
3166
3190
  }
3167
3191
  function programQuery(input) {
3168
- return {
3192
+ return brandOperationKind({
3169
3193
  name: input.name,
3170
3194
  path: input.path,
3171
3195
  method: input.method,
3172
3196
  schema: input.schema,
3173
- };
3197
+ }, 'query');
3174
3198
  }
3175
3199
  function stackQuery(input) {
3176
- return {
3200
+ return brandOperationKind({
3177
3201
  name: input.name,
3178
3202
  path: input.path,
3179
3203
  method: input.method,
3180
3204
  schema: input.schema,
3181
- };
3205
+ }, 'query');
3182
3206
  }
3183
3207
 
3184
3208
  function joinUrl(baseUrl, path) {
@@ -3199,6 +3223,19 @@ function decodeBase64(encoded) {
3199
3223
  }
3200
3224
  throw new Error('No base64 decoder available in this environment');
3201
3225
  }
3226
+ const MAX_BATCH_ADDRESSES = 100;
3227
+ function toRawAccount(body) {
3228
+ if (!body) {
3229
+ return null;
3230
+ }
3231
+ return {
3232
+ address: body.address,
3233
+ ownerProgram: body.ownerProgram,
3234
+ lamports: decimalU64(body.lamports, 'lamports'),
3235
+ executable: body.executable,
3236
+ data: decodeBase64(body.data),
3237
+ };
3238
+ }
3202
3239
  function decimalU64(value, field) {
3203
3240
  if (!/^\d+$/.test(value)) {
3204
3241
  throw new TypeError(`${field} must be a decimal u64 string`);
@@ -3286,17 +3323,33 @@ function createChainClient(httpBaseUrl, fetchImpl) {
3286
3323
  async account(address) {
3287
3324
  const path = `/chain/accounts/${encodeURIComponent(address)}`;
3288
3325
  const response = await fetchImpl(joinUrl(httpBaseUrl, path));
3326
+ return toRawAccount(await parseReadResponse(response, path));
3327
+ },
3328
+ async accounts(addresses) {
3329
+ // Copied before anything else: `readonly string[]` accepts a mutable array, so a caller can
3330
+ // splice it while the request is in flight and the cardinality check below would then compare
3331
+ // the response against a list that is no longer what was asked for. The Python client copies
3332
+ // for the same reason.
3333
+ const requested = [...addresses];
3334
+ if (requested.length > MAX_BATCH_ADDRESSES) {
3335
+ throw new RangeError(`addresses exceeds the ${MAX_BATCH_ADDRESSES}-address limit for one batch`);
3336
+ }
3337
+ if (requested.length === 0) {
3338
+ return [];
3339
+ }
3340
+ const path = '/chain/accounts';
3341
+ const response = await fetchImpl(joinUrl(httpBaseUrl, path), {
3342
+ method: 'POST',
3343
+ headers: { 'content-type': 'application/json' },
3344
+ body: JSON.stringify({ addresses: requested }),
3345
+ });
3289
3346
  const body = await parseReadResponse(response, path);
3290
- if (!body) {
3291
- return null;
3347
+ // A different count would shift every later account onto the wrong address.
3348
+ if (body.items.length !== requested.length) {
3349
+ throw new TypeError(`Invalid chain response for '${path}': expected ${requested.length} items, got ${body.items.length}`);
3292
3350
  }
3293
- return {
3294
- address: body.address,
3295
- ownerProgram: body.ownerProgram,
3296
- lamports: body.lamports,
3297
- executable: body.executable,
3298
- data: decodeBase64(body.data),
3299
- };
3351
+ // Positionally aligned with `requested`; absent accounts arrive as null.
3352
+ return body.items.map(toRawAccount);
3300
3353
  },
3301
3354
  async mint(address) {
3302
3355
  const path = `/chain/mints/${encodeURIComponent(address)}`;
@@ -4805,12 +4858,18 @@ function serializeValue(value, type) {
4805
4858
  if ('vec' in type) {
4806
4859
  return serializeVec(value, type.vec);
4807
4860
  }
4861
+ if ('vecU64Len' in type) {
4862
+ return serializeVec(value, type.vecU64Len, 8);
4863
+ }
4808
4864
  if ('option' in type) {
4809
4865
  return serializeOption(value, type.option);
4810
4866
  }
4811
4867
  if ('array' in type) {
4812
4868
  return serializeArray(value, type.array[0], type.array[1]);
4813
4869
  }
4870
+ if ('tuple' in type) {
4871
+ return serializeTuple(value, type.tuple);
4872
+ }
4814
4873
  if ('hashMap' in type) {
4815
4874
  return serializeHashMap(value, type.hashMap[0], type.hashMap[1]);
4816
4875
  }
@@ -4838,6 +4897,15 @@ function serializeStruct(value, fields) {
4838
4897
  }
4839
4898
  return buffer.Buffer.concat(buffers);
4840
4899
  }
4900
+ function serializeTuple(value, elementTypes) {
4901
+ if (!Array.isArray(value)) {
4902
+ throw new Error(`Tuple value must be an array, got ${typeof value}`);
4903
+ }
4904
+ if (value.length !== elementTypes.length) {
4905
+ throw new Error(`Tuple length mismatch: expected ${elementTypes.length}, got ${value.length}`);
4906
+ }
4907
+ return buffer.Buffer.concat(elementTypes.map((elementType, index) => serializeValue(value[index], elementType)));
4908
+ }
4841
4909
  function serializeHashMap(value, keyType, valueType) {
4842
4910
  if (keyType !== 'string') {
4843
4911
  throw new Error(`Instruction hashMap keys must use the 'string' schema, got ${JSON.stringify(keyType)}`);
@@ -5011,9 +5079,15 @@ function serializePrimitive(value, type) {
5011
5079
  throw new Error(`Unknown primitive type: ${type}`);
5012
5080
  }
5013
5081
  }
5014
- function serializeVec(values, elementType) {
5015
- const len = buffer.Buffer.alloc(4);
5016
- len.writeUInt32LE(values.length, 0);
5082
+ // `lengthBytes`: 4 for Borsh, 8 for bincode-style sequences.
5083
+ function serializeVec(values, elementType, lengthBytes = 4) {
5084
+ const len = buffer.Buffer.alloc(lengthBytes);
5085
+ if (lengthBytes === 8) {
5086
+ len.writeBigUInt64LE(BigInt(values.length), 0);
5087
+ }
5088
+ else {
5089
+ len.writeUInt32LE(values.length, 0);
5090
+ }
5017
5091
  const elementBuffers = values.map(v => serializeValue(v, elementType));
5018
5092
  return buffer.Buffer.concat([len, ...elementBuffers]);
5019
5093
  }
@@ -7245,22 +7319,22 @@ async function createSession(definition, ...args) {
7245
7319
  }
7246
7320
 
7247
7321
  function instructionOperation(prepare) {
7248
- return {
7322
+ return brandOperationKind({
7249
7323
  kind: 'instruction',
7250
7324
  prepare: async (input) => prepare(input),
7251
- };
7325
+ }, 'instruction');
7252
7326
  }
7253
7327
  function transactionOperation(prepare) {
7254
- return {
7328
+ return brandOperationKind({
7255
7329
  kind: 'transaction',
7256
7330
  prepare: async (input) => prepare(input),
7257
- };
7331
+ }, 'transaction');
7258
7332
  }
7259
7333
  function flowOperation(prepare) {
7260
- return {
7334
+ return brandOperationKind({
7261
7335
  kind: 'flow',
7262
7336
  prepare: async (input) => prepare(input),
7263
- };
7337
+ }, 'flow');
7264
7338
  }
7265
7339
 
7266
7340
  function chainAccountLoader(chain) {
@@ -7431,6 +7505,7 @@ exports.DEFAULT_MAX_ENTRIES_PER_VIEW = DEFAULT_MAX_ENTRIES_PER_VIEW;
7431
7505
  exports.FrameProcessor = FrameProcessor;
7432
7506
  exports.InstructionError = InstructionError;
7433
7507
  exports.MemoryAdapter = MemoryAdapter;
7508
+ exports.OPERATION_KIND = OPERATION_KIND;
7434
7509
  exports.OperationCallbackError = OperationCallbackError;
7435
7510
  exports.OperationExecutionError = OperationExecutionError;
7436
7511
  exports.PROGRAM_OPERATION_EXTENSIONS = PROGRAM_OPERATION_EXTENSIONS;
@@ -7494,6 +7569,7 @@ exports.formatPreparedOperation = formatPreparedOperation;
7494
7569
  exports.formatProgramError = formatProgramError;
7495
7570
  exports.formatRawToUi = formatRawToUi;
7496
7571
  exports.getMintDecimals = getMintDecimals;
7572
+ exports.getOperationKind = getOperationKind;
7497
7573
  exports.getProgramRuntimeExtensions = getProgramRuntimeExtensions;
7498
7574
  exports.getStackRuntimeExtensions = getStackRuntimeExtensions;
7499
7575
  exports.getTransactionFailureOutcome = getTransactionFailureOutcome;