@usearete/sdk 0.13.0 → 0.15.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/dist/index.cjs CHANGED
@@ -3123,6 +3123,195 @@ function createTypedViews(stack, storage, subscriptionRegistry) {
3123
3123
  return views;
3124
3124
  }
3125
3125
 
3126
+ /**
3127
+ * Wallet adapter boundary for the Arete SDK.
3128
+ *
3129
+ * The core SDK is intentionally RPC-free: it only constructs `BuiltInstruction`
3130
+ * objects. Everything network-related (recent blockhash, message compilation,
3131
+ * signing, sending, and confirmation) lives behind the `WalletAdapter`
3132
+ * boundary, implemented by adapters that wrap the Solana library of your choice
3133
+ * (@solana/web3.js, @solana/kit, a raw Keypair signer for scripts, etc.).
3134
+ */
3135
+ /** Canonical resource option keys, in contract order. */
3136
+ const TRANSACTION_RESOURCE_OPTION_KEYS = [
3137
+ 'computeUnitLimit',
3138
+ 'loadedAccountsDataSizeLimit',
3139
+ 'heapSize',
3140
+ 'priorityFeeLamports',
3141
+ 'computeUnitPriceMicroLamports',
3142
+ ];
3143
+ /** Typed rejection for malformed or unsupported build options. */
3144
+ class TransactionOptionsError extends Error {
3145
+ constructor(code, message, details = {}) {
3146
+ super(message);
3147
+ this.name = 'TransactionOptionsError';
3148
+ this.code = code;
3149
+ this.option = details.option;
3150
+ this.requestedVersion = details.requestedVersion;
3151
+ this.supportedVersions = details.supportedVersions;
3152
+ }
3153
+ }
3154
+ const U32_MAX = 0xffffffffn;
3155
+ const U64_MAX = (1n << 64n) - 1n;
3156
+ const DECIMAL = /^\d+$/;
3157
+ function inRange(value, max, option) {
3158
+ if (value > max) {
3159
+ throw new TransactionOptionsError('invalid_transaction_option', `Transaction option '${option}' exceeds its maximum of ${max}`, { option });
3160
+ }
3161
+ return value;
3162
+ }
3163
+ function parseUnits(value, option) {
3164
+ if (value === undefined)
3165
+ return undefined;
3166
+ if (typeof value === 'bigint') {
3167
+ if (value < 0n) {
3168
+ throw new TransactionOptionsError('invalid_transaction_option', `Transaction option '${option}' must not be negative`, { option });
3169
+ }
3170
+ return inRange(value, U32_MAX, option);
3171
+ }
3172
+ if (typeof value === 'number') {
3173
+ if (!Number.isInteger(value) || value < 0) {
3174
+ throw new TransactionOptionsError('invalid_transaction_option', `Transaction option '${option}' must be a non-negative integer or decimal string, `
3175
+ + `received ${value}`, { option });
3176
+ }
3177
+ return inRange(BigInt(value), U32_MAX, option);
3178
+ }
3179
+ if (typeof value === 'string' && DECIMAL.test(value)) {
3180
+ return inRange(BigInt(value), U32_MAX, option);
3181
+ }
3182
+ throw new TransactionOptionsError('invalid_transaction_option', `Transaction option '${option}' must be a non-negative integer or decimal string`, { option });
3183
+ }
3184
+ function parseLamports(value, option) {
3185
+ if (value === undefined)
3186
+ return undefined;
3187
+ if (typeof value === 'number') {
3188
+ throw new TransactionOptionsError('invalid_transaction_option', `Transaction option '${option}' must be a bigint or decimal string, never a number: `
3189
+ + 'every JavaScript number is a double, so a u64 passed as one may already have lost '
3190
+ + `precision before it reached the SDK (received ${value})`, { option });
3191
+ }
3192
+ if (typeof value === 'bigint') {
3193
+ if (value < 0n) {
3194
+ throw new TransactionOptionsError('invalid_transaction_option', `Transaction option '${option}' must not be negative`, { option });
3195
+ }
3196
+ return inRange(value, U64_MAX, option);
3197
+ }
3198
+ if (typeof value === 'string' && DECIMAL.test(value)) {
3199
+ return inRange(BigInt(value), U64_MAX, option);
3200
+ }
3201
+ throw new TransactionOptionsError('invalid_transaction_option', `Transaction option '${option}' must be a bigint or decimal string`, { option });
3202
+ }
3203
+ /**
3204
+ * Merge execution defaults with per-call send options.
3205
+ *
3206
+ * `resources` merges key by key, so a per-call fee does not discard a
3207
+ * configured compute budget — except for the two fee fields, which are one
3208
+ * slot: setting either clears the other, or the merged budget would hold both
3209
+ * and be refused as mutually exclusive. Shared by every entry point that has
3210
+ * defaults to merge; duplicating this logic is how `session` came to disagree
3211
+ * with `Arete.execute`.
3212
+ */
3213
+ function mergeSendOptions(defaults, override) {
3214
+ if (!defaults)
3215
+ return override;
3216
+ if (!override)
3217
+ return defaults;
3218
+ const inherited = { ...defaults.resources };
3219
+ if (override.resources?.priorityFeeLamports !== undefined ||
3220
+ override.resources?.computeUnitPriceMicroLamports !== undefined) {
3221
+ delete inherited.priorityFeeLamports;
3222
+ delete inherited.computeUnitPriceMicroLamports;
3223
+ }
3224
+ const resources = defaults.resources || override.resources
3225
+ ? { ...inherited, ...override.resources }
3226
+ : undefined;
3227
+ return { ...defaults, ...override, ...(resources ? { resources } : {}) };
3228
+ }
3229
+ /**
3230
+ * Validate build options against an adapter's declared capability and
3231
+ * normalize every quantity to a bigint.
3232
+ *
3233
+ * Rejections are never silent downgrades: an explicit version the adapter does
3234
+ * not advertise fails, and a fee field used against the wrong version fails
3235
+ * instead of being converted.
3236
+ */
3237
+ function resolveTransactionBuildOptions(options, capability) {
3238
+ const requested = options?.transactionVersion;
3239
+ if (requested !== undefined && requested !== 'legacy' && requested !== 0 && requested !== 1) {
3240
+ throw new TransactionOptionsError('invalid_transaction_option', `Unknown transactionVersion ${JSON.stringify(requested)}: expected 'legacy', 0, or 1`, { option: 'transactionVersion' });
3241
+ }
3242
+ const supported = capability?.supportedTransactionVersions;
3243
+ if (requested !== undefined) {
3244
+ // Undeclared capability means unknown, not unsupported: old versions keep
3245
+ // working, and only an explicit V1 request needs proof of support.
3246
+ const unsupported = supported ? !supported.includes(requested) : requested === 1;
3247
+ if (unsupported) {
3248
+ throw new TransactionOptionsError('unsupported_transaction_version', `Wallet adapter does not support transaction version ${JSON.stringify(requested)}`
3249
+ + (supported
3250
+ ? ` (supported: ${supported.map((version) => JSON.stringify(version)).join(', ')})`
3251
+ : ' (adapter declares no supported versions)'), { option: 'transactionVersion', requestedVersion: requested, supportedVersions: supported });
3252
+ }
3253
+ }
3254
+ const resources = options?.resources;
3255
+ if (resources !== undefined) {
3256
+ if (typeof resources !== 'object' || resources === null || Array.isArray(resources)) {
3257
+ throw new TransactionOptionsError('invalid_transaction_option', 'Transaction option \'resources\' must be an object of canonical resource options', { option: 'resources' });
3258
+ }
3259
+ // Closed key set: an unrecognized budget key is a rejection, never a
3260
+ // silently ignored passthrough.
3261
+ const unknownKey = Object.keys(resources).find((key) => !TRANSACTION_RESOURCE_OPTION_KEYS.includes(key));
3262
+ if (unknownKey) {
3263
+ throw new TransactionOptionsError('unsupported_resource_option', `Unknown resource option '${unknownKey}': expected one of `
3264
+ + TRANSACTION_RESOURCE_OPTION_KEYS.join(', '), { option: unknownKey });
3265
+ }
3266
+ }
3267
+ const honoured = capability?.supportedResourceOptions;
3268
+ if (honoured) {
3269
+ const rejected = TRANSACTION_RESOURCE_OPTION_KEYS.find((key) => resources?.[key] !== undefined && !honoured.includes(key));
3270
+ if (rejected) {
3271
+ throw new TransactionOptionsError('unsupported_resource_option', `Wallet adapter does not apply the '${rejected}' resource option`, { option: rejected });
3272
+ }
3273
+ }
3274
+ const version = requested ?? 0;
3275
+ if (resources?.priorityFeeLamports !== undefined
3276
+ && resources?.computeUnitPriceMicroLamports !== undefined) {
3277
+ throw new TransactionOptionsError('invalid_transaction_option', 'priorityFeeLamports and computeUnitPriceMicroLamports are mutually exclusive', { option: 'priorityFeeLamports', requestedVersion: version });
3278
+ }
3279
+ if (resources?.priorityFeeLamports !== undefined && version !== 1) {
3280
+ throw new TransactionOptionsError('unsupported_resource_option', `priorityFeeLamports requires transaction version 1, not ${JSON.stringify(version)}`, { option: 'priorityFeeLamports', requestedVersion: version });
3281
+ }
3282
+ if (resources?.computeUnitPriceMicroLamports !== undefined && version === 1) {
3283
+ throw new TransactionOptionsError('unsupported_resource_option', 'computeUnitPriceMicroLamports applies to legacy/v0 only; version 1 uses priorityFeeLamports', { option: 'computeUnitPriceMicroLamports', requestedVersion: version });
3284
+ }
3285
+ return {
3286
+ transactionVersion: version,
3287
+ resources: {
3288
+ computeUnitLimit: parseUnits(resources?.computeUnitLimit, 'computeUnitLimit'),
3289
+ loadedAccountsDataSizeLimit: parseUnits(resources?.loadedAccountsDataSizeLimit, 'loadedAccountsDataSizeLimit'),
3290
+ heapSize: parseUnits(resources?.heapSize, 'heapSize'),
3291
+ priorityFeeLamports: parseLamports(resources?.priorityFeeLamports, 'priorityFeeLamports'),
3292
+ computeUnitPriceMicroLamports: parseLamports(resources?.computeUnitPriceMicroLamports, 'computeUnitPriceMicroLamports'),
3293
+ },
3294
+ };
3295
+ }
3296
+ /**
3297
+ * Boundary form of a resolved resource budget: flat canonical camelCase keys,
3298
+ * every present value a decimal string, absent keys omitted.
3299
+ *
3300
+ * Mirrors Rust `TransactionResourceOptions::to_json()` and Python `to_wire()`.
3301
+ * Key order is not part of the contract (Rust sorts, Python uses declaration
3302
+ * order); the keys and their decimal-string values are. bigint stays the
3303
+ * in-process type; `JSON.stringify` cannot emit one.
3304
+ */
3305
+ function toWireResourceOptions(resources) {
3306
+ const wire = {};
3307
+ for (const key of TRANSACTION_RESOURCE_OPTION_KEYS) {
3308
+ const value = resources[key];
3309
+ if (value !== undefined)
3310
+ wire[key] = value.toString(10);
3311
+ }
3312
+ return wire;
3313
+ }
3314
+
3126
3315
  /**
3127
3316
  * Non-enumerable brand attached by the operation and read factories so
3128
3317
  * tooling (e.g. the knowledge-layer extractor's runtime walk) can classify
@@ -3473,6 +3662,7 @@ function createTransactionTransport(baseUrl, authenticatedFetch) {
3473
3662
  err: value.err ?? null,
3474
3663
  logs: value.logs ?? null,
3475
3664
  unitsConsumed: optionalBigint(value.unitsConsumed, 'unitsConsumed'),
3665
+ loadedAccountsDataSize: optionalBigint(value.loadedAccountsDataSize, 'loadedAccountsDataSize'),
3476
3666
  accounts: value.accounts,
3477
3667
  };
3478
3668
  },
@@ -6249,6 +6439,7 @@ async function inspectPreparedOperation(wallet, operation, options, context) {
6249
6439
  if (!wallet?.inspectTransaction) {
6250
6440
  throw new Error('Wallet adapter does not support unsigned transaction inspection');
6251
6441
  }
6442
+ resolveTransactionBuildOptions(options, wallet);
6252
6443
  const transaction = operation.plan.transactions[0];
6253
6444
  const description = describePreparedOperation(operation);
6254
6445
  const inspection = context
@@ -6943,13 +7134,17 @@ let Arete$1 = class Arete {
6943
7134
  cause,
6944
7135
  });
6945
7136
  }
7137
+ const sendOptions = {
7138
+ ...(options?.send ?? {}),
7139
+ };
7140
+ if (options?.signers !== undefined) {
7141
+ sendOptions.signers = options.signers;
7142
+ }
7143
+ // Version/resource options are validated before anything reaches the
7144
+ // adapter, so an unsupported request throws the typed options error rather
7145
+ // than a wrapped execution failure.
7146
+ resolveTransactionBuildOptions(sendOptions, wallet);
6946
7147
  try {
6947
- const sendOptions = {
6948
- ...(options?.send ?? {}),
6949
- };
6950
- if (options?.signers !== undefined) {
6951
- sendOptions.signers = options.signers;
6952
- }
6953
7148
  const result = await wallet.signAndSend(instructions, sendOptions, {
6954
7149
  transactionTransport: options?.transactionTransport ?? this._transactions,
6955
7150
  });
@@ -6963,9 +7158,7 @@ let Arete$1 = class Arete {
6963
7158
  const defaults = this.executionDefaults;
6964
7159
  return executePreparedOperation(this, prepared, {
6965
7160
  wallet: options?.wallet ?? defaults?.wallet,
6966
- send: defaults?.send || options?.send
6967
- ? { ...(defaults?.send ?? {}), ...(options?.send ?? {}) }
6968
- : undefined,
7161
+ send: mergeSendOptions(defaults?.send, options?.send),
6969
7162
  signers: options?.signers ?? defaults?.signers,
6970
7163
  transactionTransport: options?.transactionTransport ?? defaults?.transactionTransport,
6971
7164
  signerRegistry: options?.signerRegistry ?? defaults?.signerRegistry,
@@ -7279,9 +7472,7 @@ async function createSession(definition, ...args) {
7279
7472
  return executionHost.transaction(instructions, {
7280
7473
  wallet: transactionOptions?.wallet ?? defaults?.wallet,
7281
7474
  transactionTransport: transactionOptions?.transactionTransport ?? transactions,
7282
- send: defaults?.send || transactionOptions?.send
7283
- ? { ...(defaults?.send ?? {}), ...(transactionOptions?.send ?? {}) }
7284
- : undefined,
7475
+ send: mergeSendOptions(defaults?.send, transactionOptions?.send),
7285
7476
  errors: transactionOptions?.errors,
7286
7477
  signers: signers.length > 0 ? signers : undefined,
7287
7478
  });
@@ -7292,9 +7483,7 @@ async function createSession(definition, ...args) {
7292
7483
  return executionHost.execute(prepared, {
7293
7484
  wallet: executionOptions?.wallet ?? defaults?.wallet,
7294
7485
  transactionTransport: executionOptions?.transactionTransport ?? defaults?.transactionTransport ?? transactions,
7295
- send: defaults?.send || executionOptions?.send
7296
- ? { ...(defaults?.send ?? {}), ...(executionOptions?.send ?? {}) }
7297
- : undefined,
7486
+ send: mergeSendOptions(defaults?.send, executionOptions?.send),
7298
7487
  signers: configuredSigners,
7299
7488
  signerRegistry,
7300
7489
  availableSignerAddresses: executionOptions?.availableSignerAddresses ?? defaults?.availableSignerAddresses,
@@ -7517,7 +7706,9 @@ exports.STACK_RUNTIME_EXTENSIONS = STACK_RUNTIME_EXTENSIONS;
7517
7706
  exports.SYSTEM_PROGRAM_ADDRESS = SYSTEM_PROGRAM_ADDRESS;
7518
7707
  exports.SubscriptionRegistry = SubscriptionRegistry;
7519
7708
  exports.TOKEN_2022_PROGRAM_ADDRESS = TOKEN_2022_PROGRAM_ADDRESS;
7709
+ exports.TRANSACTION_RESOURCE_OPTION_KEYS = TRANSACTION_RESOURCE_OPTION_KEYS;
7520
7710
  exports.TransactionExecutionError = TransactionExecutionError;
7711
+ exports.TransactionOptionsError = TransactionOptionsError;
7521
7712
  exports.TransactionTransportError = TransactionTransportError;
7522
7713
  exports.account = account;
7523
7714
  exports.appendFlowTransactions = appendFlowTransactions;
@@ -7601,6 +7792,7 @@ exports.resolveAmount = resolveAmount;
7601
7792
  exports.resolveAmountToRaw = resolveAmountToRaw;
7602
7793
  exports.resolveAmountsToRaw = resolveAmountsToRaw;
7603
7794
  exports.resolveTokenProgramAddress = resolveTokenProgramAddress;
7795
+ exports.resolveTransactionBuildOptions = resolveTransactionBuildOptions;
7604
7796
  exports.safeToRawAmount = safeToRawAmount;
7605
7797
  exports.serializeInstructionData = serializeInstructionData;
7606
7798
  exports.serializeViewKey = serializeViewKey;
@@ -7608,6 +7800,7 @@ exports.stackQuery = stackQuery;
7608
7800
  exports.stringifyBigints = stringifyBigints;
7609
7801
  exports.toJsonValue = toJsonValue;
7610
7802
  exports.toRawAmount = toRawAmount;
7803
+ exports.toWireResourceOptions = toWireResourceOptions;
7611
7804
  exports.transactionOperation = transactionOperation;
7612
7805
  exports.unwrapOperationExecutionError = unwrapOperationExecutionError;
7613
7806
  exports.validateAccountResolution = validateAccountResolution;