Socket
Socket
Sign inDemoInstall

@mysten/sui

Package Overview
Dependencies
Maintainers
0
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mysten/sui - npm Package Compare versions

Comparing version 0.0.0-experimental-20240614013711 to 0.0.0-experimental-20240621004420

8

CHANGELOG.md
# @mysten/sui.js
## 0.0.0-experimental-20240614013711
## 0.0.0-experimental-20240621004420
### Minor Changes
- fef99d377f: Update parallel executor class to handle gasPrice and budgeting to remove extra rpc calls during execution"
## 1.1.2
### Patch Changes

@@ -6,0 +12,0 @@

5

dist/cjs/transactions/executor/caching.d.ts
import { bcs } from '../../bcs/index.js';
import type { ExecuteTransactionBlockParams, SuiClient } from '../../client/index.js';
import type { Signer } from '../../cryptography/keypair.js';
import type { BuildTransactionOptions } from '../json-rpc-resolver.js';
import type { ObjectCacheOptions } from '../ObjectCache.js';

@@ -18,5 +19,5 @@ import { ObjectCache } from '../ObjectCache.js';

reset(): Promise<void>;
buildTransaction({ transaction }: {
buildTransaction({ transaction, ...options }: {
transaction: Transaction;
}): Promise<Uint8Array>;
} & BuildTransactionOptions): Promise<Uint8Array>;
executeTransaction({ transaction, options, ...input }: {

@@ -23,0 +24,0 @@ transaction: Transaction | Uint8Array;

@@ -63,6 +63,10 @@ "use strict";

}
async buildTransaction({ transaction }) {
async buildTransaction({
transaction,
...options
}) {
transaction.addBuildPlugin(this.cache.asPlugin());
return transaction.build({
client: __privateGet(this, _client)
client: __privateGet(this, _client),
...options
});

@@ -69,0 +73,0 @@ }

@@ -8,6 +8,19 @@ import type { SuiClient } from '../../client/index.js';

signer: Signer;
/** The number of coins to create in a batch when refilling the gas pool */
coinBatchSize?: number;
/** The initial balance of each coin created for the gas pool */
initialCoinBalance?: bigint;
/** The minimum balance of a coin that can be reused for future transactions. If the gasCoin is below this value, it will be used when refilling the gasPool */
minimumCoinBalance?: bigint;
/** The gasBudget to use if the transaction has not defined it's own gasBudget, defaults to `minimumCoinBalance` */
defaultGasBudget?: bigint;
/**
* Time to wait before/after the expected epoch boundary before re-fetching the gas pool (in milliseconds).
* Building transactions will be paused for up to 2x this duration around each epoch boundary to ensure the
* gas price is up-to-date for the next epoch.
* */
epochBoundaryWindow?: number;
/** The maximum number of transactions that can be execute in parallel, this also determines the maximum number of gas coins that will be created */
maxPoolSize?: number;
/** An initial list of coins used to fund the gas pool, uses all owned SUI coins by default */
sourceCoins?: string[];

@@ -14,0 +27,0 @@ }

@@ -37,2 +37,10 @@ "use strict";

};
var __privateWrapper = (obj, member, setter, getter) => ({
set _(value) {
__privateSet(obj, member, value, setter);
},
get _() {
return __privateGet(obj, member, getter);
}
});
var __privateMethod = (obj, member, method) => {

@@ -53,3 +61,3 @@ __accessCheck(obj, member, "access private method");

var import_serial = require("./serial.js");
var _signer, _client, _coinBatchSize, _initialCoinBalance, _minimumCoinBalance, _maxPoolSize, _sourceCoins, _coinPool, _cache, _objectIdQueues, _buildQueue, _executeQueue, _getUsedObjects, getUsedObjects_fn, _execute, execute_fn, _getGasCoin, getGasCoin_fn, _refillCoinPool, refillCoinPool_fn;
var _signer, _client, _coinBatchSize, _initialCoinBalance, _minimumCoinBalance, _epochBoundaryWindow, _defaultGasBudget, _maxPoolSize, _sourceCoins, _coinPool, _cache, _objectIdQueues, _buildQueue, _executeQueue, _lastDigest, _cacheLock, _pendingTransactions, _gasPrice, _getUsedObjects, getUsedObjects_fn, _execute, execute_fn, _updateCache, updateCache_fn, _waitForLastDigest, waitForLastDigest_fn, _getGasCoin, getGasCoin_fn, _getGasPrice, getGasPrice_fn, _refillCoinPool, refillCoinPool_fn;
const PARALLEL_EXECUTOR_DEFAULTS = {

@@ -59,3 +67,4 @@ coinBatchSize: 20,

minimumCoinBalance: 50000000n,
maxPoolSize: 50
maxPoolSize: 50,
epochBoundaryWindow: 1e3
};

@@ -66,3 +75,7 @@ class ParallelTransactionExecutor {

__privateAdd(this, _execute);
/** Helper for synchronizing cache updates, by ensuring only one update happens at a time. This can also be used to wait for any pending cache updates */
__privateAdd(this, _updateCache);
__privateAdd(this, _waitForLastDigest);
__privateAdd(this, _getGasCoin);
__privateAdd(this, _getGasPrice);
__privateAdd(this, _refillCoinPool);

@@ -74,2 +87,4 @@ __privateAdd(this, _signer, void 0);

__privateAdd(this, _minimumCoinBalance, void 0);
__privateAdd(this, _epochBoundaryWindow, void 0);
__privateAdd(this, _defaultGasBudget, void 0);
__privateAdd(this, _maxPoolSize, void 0);

@@ -82,2 +97,6 @@ __privateAdd(this, _sourceCoins, void 0);

__privateAdd(this, _executeQueue, void 0);
__privateAdd(this, _lastDigest, null);
__privateAdd(this, _cacheLock, null);
__privateAdd(this, _pendingTransactions, 0);
__privateAdd(this, _gasPrice, null);
__privateSet(this, _signer, options.signer);

@@ -88,2 +107,4 @@ __privateSet(this, _client, options.client);

__privateSet(this, _minimumCoinBalance, options.minimumCoinBalance ?? PARALLEL_EXECUTOR_DEFAULTS.minimumCoinBalance);
__privateSet(this, _defaultGasBudget, options.defaultGasBudget ?? __privateGet(this, _minimumCoinBalance));
__privateSet(this, _epochBoundaryWindow, options.epochBoundaryWindow ?? PARALLEL_EXECUTOR_DEFAULTS.epochBoundaryWindow);
__privateSet(this, _maxPoolSize, options.maxPoolSize ?? PARALLEL_EXECUTOR_DEFAULTS.maxPoolSize);

@@ -98,3 +119,4 @@ __privateSet(this, _cache, new import_caching.CachingTransactionExecutor({

resetCache() {
return __privateGet(this, _cache).reset();
__privateSet(this, _gasPrice, null);
return __privateMethod(this, _updateCache, updateCache_fn).call(this, () => __privateGet(this, _cache).reset());
}

@@ -136,2 +158,4 @@ async executeTransaction(transaction) {

_minimumCoinBalance = new WeakMap();
_epochBoundaryWindow = new WeakMap();
_defaultGasBudget = new WeakMap();
_maxPoolSize = new WeakMap();

@@ -144,2 +168,6 @@ _sourceCoins = new WeakMap();

_executeQueue = new WeakMap();
_lastDigest = new WeakMap();
_cacheLock = new WeakMap();
_pendingTransactions = new WeakMap();
_gasPrice = new WeakMap();
_getUsedObjects = new WeakSet();

@@ -172,4 +200,14 @@ getUsedObjects_fn = async function(transaction) {

try {
const bytes = await __privateGet(this, _buildQueue).runTask(async () => {
transaction.setSenderIfNotSet(__privateGet(this, _signer).toSuiAddress());
await __privateGet(this, _buildQueue).runTask(async () => {
const data = transaction.getData();
if (!data.gasData.price) {
transaction.setGasPrice(await __privateMethod(this, _getGasPrice, getGasPrice_fn).call(this));
}
if (!data.gasData.budget) {
transaction.setGasBudget(__privateGet(this, _defaultGasBudget));
}
await __privateMethod(this, _updateCache, updateCache_fn).call(this);
gasCoin = await __privateMethod(this, _getGasCoin, getGasCoin_fn).call(this);
__privateWrapper(this, _pendingTransactions)._++;
transaction.setGasPayment([

@@ -182,5 +220,5 @@ {

]);
transaction.setSenderIfNotSet(__privateGet(this, _signer).toSuiAddress());
return __privateGet(this, _cache).buildTransaction({ transaction });
await __privateGet(this, _cache).buildTransaction({ transaction, onlyTransactionKind: true });
});
const bytes = await transaction.build({ client: __privateGet(this, _client) });
const { signature } = await __privateGet(this, _signer).signTransaction(bytes);

@@ -214,2 +252,3 @@ const results = await __privateGet(this, _cache).executeTransaction({

}
__privateSet(this, _lastDigest, results.digest);
return {

@@ -226,3 +265,8 @@ digest: results.digest,

}
await __privateGet(this, _cache).cache.deleteObjects([...usedObjects]);
await __privateMethod(this, _updateCache, updateCache_fn).call(this, async () => {
await Promise.all([
__privateGet(this, _cache).cache.deleteObjects([...usedObjects]),
__privateMethod(this, _waitForLastDigest, waitForLastDigest_fn).call(this)
]);
});
throw error;

@@ -238,7 +282,29 @@ } finally {

});
__privateWrapper(this, _pendingTransactions)._--;
}
};
_updateCache = new WeakSet();
updateCache_fn = async function(fn) {
if (__privateGet(this, _cacheLock)) {
await __privateGet(this, _cacheLock);
}
__privateSet(this, _cacheLock, fn?.().then(
() => {
__privateSet(this, _cacheLock, null);
},
() => {
}
) ?? null);
};
_waitForLastDigest = new WeakSet();
waitForLastDigest_fn = async function() {
const digest = __privateGet(this, _lastDigest);
if (digest) {
__privateSet(this, _lastDigest, null);
await __privateGet(this, _client).waitForTransaction({ digest });
}
};
_getGasCoin = new WeakSet();
getGasCoin_fn = async function() {
if (__privateGet(this, _coinPool).length === 0 && __privateGet(this, _executeQueue).activeTasks <= __privateGet(this, _maxPoolSize)) {
if (__privateGet(this, _coinPool).length === 0 && __privateGet(this, _pendingTransactions) <= __privateGet(this, _maxPoolSize)) {
await __privateMethod(this, _refillCoinPool, refillCoinPool_fn).call(this);

@@ -252,2 +318,22 @@ }

};
_getGasPrice = new WeakSet();
getGasPrice_fn = async function() {
const remaining = __privateGet(this, _gasPrice) ? __privateGet(this, _gasPrice).expiration - __privateGet(this, _epochBoundaryWindow) - Date.now() : 0;
if (remaining > 0) {
return __privateGet(this, _gasPrice).price;
}
if (__privateGet(this, _gasPrice)) {
const timeToNextEpoch = Math.max(
__privateGet(this, _gasPrice).expiration + __privateGet(this, _epochBoundaryWindow) - Date.now(),
1e3
);
await new Promise((resolve) => setTimeout(resolve, timeToNextEpoch));
}
const state = await __privateGet(this, _client).getLatestSuiSystemState();
__privateSet(this, _gasPrice, {
price: BigInt(state.referenceGasPrice),
expiration: Number.parseInt(state.epochStartTimestampMs, 10) + Number.parseInt(state.epochDurationMs, 10)
});
return __privateMethod(this, _getGasPrice, getGasPrice_fn).call(this);
};
_refillCoinPool = new WeakSet();

@@ -257,3 +343,3 @@ refillCoinPool_fn = async function() {

__privateGet(this, _coinBatchSize),
__privateGet(this, _maxPoolSize) - (__privateGet(this, _coinPool).length + __privateGet(this, _executeQueue).activeTasks) + 1
__privateGet(this, _maxPoolSize) - (__privateGet(this, _coinPool).length + __privateGet(this, _pendingTransactions)) + 1
);

@@ -298,2 +384,3 @@ if (batchSize === 0) {

txb.transferObjects(coinResults, address);
await __privateMethod(this, _updateCache, updateCache_fn).call(this, () => __privateMethod(this, _waitForLastDigest, waitForLastDigest_fn).call(this));
const result = await __privateGet(this, _client).signAndExecuteTransaction({

@@ -300,0 +387,0 @@ transaction: txb,

@@ -14,3 +14,3 @@ import { bcs } from '../../bcs/index.js';

buildTransaction(transaction: Transaction): Promise<Uint8Array>;
resetCache(): Promise<void>;
resetCache(): Promise<[void, void]>;
executeTransaction(transaction: Transaction | Uint8Array): Promise<{

@@ -17,0 +17,0 @@ digest: string;

@@ -37,2 +37,6 @@ "use strict";

};
var __privateMethod = (obj, member, method) => {
__accessCheck(obj, member, "access private method");
return method;
};
var serial_exports = {};

@@ -49,3 +53,3 @@ __export(serial_exports, {

var import_queue = require("./queue.js");
var _queue, _signer, _cache, _cacheGasCoin, _buildTransaction;
var _queue, _signer, _cache, _client, _lastDigest, _cacheGasCoin, _buildTransaction, _waitForLastTransaction, waitForLastTransaction_fn;
class SerialTransactionExecutor {

@@ -56,5 +60,8 @@ constructor({

}) {
__privateAdd(this, _waitForLastTransaction);
__privateAdd(this, _queue, new import_queue.SerialQueue());
__privateAdd(this, _signer, void 0);
__privateAdd(this, _cache, void 0);
__privateAdd(this, _client, void 0);
__privateAdd(this, _lastDigest, null);
__privateAdd(this, _cacheGasCoin, async (effects) => {

@@ -81,2 +88,3 @@ if (!effects.V2) {

__privateSet(this, _signer, signer);
__privateSet(this, _client, options.client);
__privateSet(this, _cache, new import_caching.CachingTransactionExecutor({

@@ -94,3 +102,3 @@ client: options.client,

resetCache() {
return __privateGet(this, _cache).reset();
return Promise.all([__privateGet(this, _cache).reset(), __privateMethod(this, _waitForLastTransaction, waitForLastTransaction_fn).call(this)]);
}

@@ -111,2 +119,3 @@ executeTransaction(transaction) {

await this.applyEffects(effects);
__privateSet(this, _lastDigest, results.digest);
return {

@@ -122,4 +131,13 @@ digest: results.digest,

_cache = new WeakMap();
_client = new WeakMap();
_lastDigest = new WeakMap();
_cacheGasCoin = new WeakMap();
_buildTransaction = new WeakMap();
_waitForLastTransaction = new WeakSet();
waitForLastTransaction_fn = async function() {
if (__privateGet(this, _lastDigest)) {
await __privateGet(this, _client).waitForTransaction({ digest: __privateGet(this, _lastDigest) });
__privateSet(this, _lastDigest, null);
}
};
function getGasCoinFromEffects(effects) {

@@ -126,0 +144,0 @@ if (!effects.V2) {

@@ -104,3 +104,3 @@ "use strict";

const objectsToResolve = transactionData.inputs.filter((input) => {
return input.UnresolvedObject && !input.UnresolvedObject.version || input.UnresolvedObject?.initialSharedVersion;
return input.UnresolvedObject && !(input.UnresolvedObject.version || input.UnresolvedObject?.initialSharedVersion);
});

@@ -126,3 +126,3 @@ const dedupedIds = [

);
const invalidObjects = Array.from(responsesById).filter(([_, obj]) => obj.error).map(([id, _obj]) => id);
const invalidObjects = Array.from(responsesById).filter(([_, obj]) => obj.error).map(([_, obj]) => JSON.stringify(obj.error));
if (invalidObjects.length) {

@@ -156,6 +156,6 @@ throw new Error(`The following input objects are invalid: ${invalidObjects.join(", ")}`);

const object = objectsById.get(id);
if (object?.initialSharedVersion) {
if (input.UnresolvedObject.initialSharedVersion ?? object?.initialSharedVersion) {
updated = import_Inputs.Inputs.SharedObjectRef({
objectId: id,
initialSharedVersion: object.initialSharedVersion,
initialSharedVersion: input.UnresolvedObject.initialSharedVersion || object?.initialSharedVersion,
mutable: isUsedAsMutable(transactionData, index)

@@ -162,0 +162,0 @@ });

@@ -154,9 +154,10 @@ "use strict";

input.UnresolvedObject.initialSharedVersion = cached2.initialSharedVersion;
} else {
if (cached2.version && !input.UnresolvedObject.version) {
input.UnresolvedObject.version = cached2.version;
}
if (cached2.digest && !input.UnresolvedObject.digest) {
input.UnresolvedObject.digest = cached2.digest;
}
}
if (cached2.version && !input.UnresolvedObject.version) {
input.UnresolvedObject.version = cached2.version;
}
if (cached2.digest && !input.UnresolvedObject.digest) {
input.UnresolvedObject.digest = cached2.digest;
}
}

@@ -163,0 +164,0 @@ await Promise.all(

@@ -1,2 +0,2 @@

export declare const PACKAGE_VERSION = "0.0.0-experimental-20240614013711";
export declare const PACKAGE_VERSION = "0.0.0-experimental-20240621004420";
export declare const TARGETED_RPC_VERSION = "1.28.0";

@@ -25,4 +25,4 @@ "use strict";

module.exports = __toCommonJS(version_exports);
const PACKAGE_VERSION = "0.0.0-experimental-20240614013711";
const PACKAGE_VERSION = "0.0.0-experimental-20240621004420";
const TARGETED_RPC_VERSION = "1.28.0";
//# sourceMappingURL=version.js.map
import { bcs } from '../../bcs/index.js';
import type { ExecuteTransactionBlockParams, SuiClient } from '../../client/index.js';
import type { Signer } from '../../cryptography/keypair.js';
import type { BuildTransactionOptions } from '../json-rpc-resolver.js';
import type { ObjectCacheOptions } from '../ObjectCache.js';

@@ -18,5 +19,5 @@ import { ObjectCache } from '../ObjectCache.js';

reset(): Promise<void>;
buildTransaction({ transaction }: {
buildTransaction({ transaction, ...options }: {
transaction: Transaction;
}): Promise<Uint8Array>;
} & BuildTransactionOptions): Promise<Uint8Array>;
executeTransaction({ transaction, options, ...input }: {

@@ -23,0 +24,0 @@ transaction: Transaction | Uint8Array;

@@ -40,6 +40,10 @@ var __accessCheck = (obj, member, msg) => {

}
async buildTransaction({ transaction }) {
async buildTransaction({
transaction,
...options
}) {
transaction.addBuildPlugin(this.cache.asPlugin());
return transaction.build({
client: __privateGet(this, _client)
client: __privateGet(this, _client),
...options
});

@@ -46,0 +50,0 @@ }

@@ -8,6 +8,19 @@ import type { SuiClient } from '../../client/index.js';

signer: Signer;
/** The number of coins to create in a batch when refilling the gas pool */
coinBatchSize?: number;
/** The initial balance of each coin created for the gas pool */
initialCoinBalance?: bigint;
/** The minimum balance of a coin that can be reused for future transactions. If the gasCoin is below this value, it will be used when refilling the gasPool */
minimumCoinBalance?: bigint;
/** The gasBudget to use if the transaction has not defined it's own gasBudget, defaults to `minimumCoinBalance` */
defaultGasBudget?: bigint;
/**
* Time to wait before/after the expected epoch boundary before re-fetching the gas pool (in milliseconds).
* Building transactions will be paused for up to 2x this duration around each epoch boundary to ensure the
* gas price is up-to-date for the next epoch.
* */
epochBoundaryWindow?: number;
/** The maximum number of transactions that can be execute in parallel, this also determines the maximum number of gas coins that will be created */
maxPoolSize?: number;
/** An initial list of coins used to fund the gas pool, uses all owned SUI coins by default */
sourceCoins?: string[];

@@ -14,0 +27,0 @@ }

@@ -19,2 +19,10 @@ var __accessCheck = (obj, member, msg) => {

};
var __privateWrapper = (obj, member, setter, getter) => ({
set _(value) {
__privateSet(obj, member, value, setter);
},
get _() {
return __privateGet(obj, member, getter);
}
});
var __privateMethod = (obj, member, method) => {

@@ -24,3 +32,3 @@ __accessCheck(obj, member, "access private method");

};
var _signer, _client, _coinBatchSize, _initialCoinBalance, _minimumCoinBalance, _maxPoolSize, _sourceCoins, _coinPool, _cache, _objectIdQueues, _buildQueue, _executeQueue, _getUsedObjects, getUsedObjects_fn, _execute, execute_fn, _getGasCoin, getGasCoin_fn, _refillCoinPool, refillCoinPool_fn;
var _signer, _client, _coinBatchSize, _initialCoinBalance, _minimumCoinBalance, _epochBoundaryWindow, _defaultGasBudget, _maxPoolSize, _sourceCoins, _coinPool, _cache, _objectIdQueues, _buildQueue, _executeQueue, _lastDigest, _cacheLock, _pendingTransactions, _gasPrice, _getUsedObjects, getUsedObjects_fn, _execute, execute_fn, _updateCache, updateCache_fn, _waitForLastDigest, waitForLastDigest_fn, _getGasCoin, getGasCoin_fn, _getGasPrice, getGasPrice_fn, _refillCoinPool, refillCoinPool_fn;
import { toB64 } from "@mysten/bcs";

@@ -36,3 +44,4 @@ import { bcs } from "../../bcs/index.js";

minimumCoinBalance: 50000000n,
maxPoolSize: 50
maxPoolSize: 50,
epochBoundaryWindow: 1e3
};

@@ -43,3 +52,7 @@ class ParallelTransactionExecutor {

__privateAdd(this, _execute);
/** Helper for synchronizing cache updates, by ensuring only one update happens at a time. This can also be used to wait for any pending cache updates */
__privateAdd(this, _updateCache);
__privateAdd(this, _waitForLastDigest);
__privateAdd(this, _getGasCoin);
__privateAdd(this, _getGasPrice);
__privateAdd(this, _refillCoinPool);

@@ -51,2 +64,4 @@ __privateAdd(this, _signer, void 0);

__privateAdd(this, _minimumCoinBalance, void 0);
__privateAdd(this, _epochBoundaryWindow, void 0);
__privateAdd(this, _defaultGasBudget, void 0);
__privateAdd(this, _maxPoolSize, void 0);

@@ -59,2 +74,6 @@ __privateAdd(this, _sourceCoins, void 0);

__privateAdd(this, _executeQueue, void 0);
__privateAdd(this, _lastDigest, null);
__privateAdd(this, _cacheLock, null);
__privateAdd(this, _pendingTransactions, 0);
__privateAdd(this, _gasPrice, null);
__privateSet(this, _signer, options.signer);

@@ -65,2 +84,4 @@ __privateSet(this, _client, options.client);

__privateSet(this, _minimumCoinBalance, options.minimumCoinBalance ?? PARALLEL_EXECUTOR_DEFAULTS.minimumCoinBalance);
__privateSet(this, _defaultGasBudget, options.defaultGasBudget ?? __privateGet(this, _minimumCoinBalance));
__privateSet(this, _epochBoundaryWindow, options.epochBoundaryWindow ?? PARALLEL_EXECUTOR_DEFAULTS.epochBoundaryWindow);
__privateSet(this, _maxPoolSize, options.maxPoolSize ?? PARALLEL_EXECUTOR_DEFAULTS.maxPoolSize);

@@ -75,3 +96,4 @@ __privateSet(this, _cache, new CachingTransactionExecutor({

resetCache() {
return __privateGet(this, _cache).reset();
__privateSet(this, _gasPrice, null);
return __privateMethod(this, _updateCache, updateCache_fn).call(this, () => __privateGet(this, _cache).reset());
}

@@ -113,2 +135,4 @@ async executeTransaction(transaction) {

_minimumCoinBalance = new WeakMap();
_epochBoundaryWindow = new WeakMap();
_defaultGasBudget = new WeakMap();
_maxPoolSize = new WeakMap();

@@ -121,2 +145,6 @@ _sourceCoins = new WeakMap();

_executeQueue = new WeakMap();
_lastDigest = new WeakMap();
_cacheLock = new WeakMap();
_pendingTransactions = new WeakMap();
_gasPrice = new WeakMap();
_getUsedObjects = new WeakSet();

@@ -149,4 +177,14 @@ getUsedObjects_fn = async function(transaction) {

try {
const bytes = await __privateGet(this, _buildQueue).runTask(async () => {
transaction.setSenderIfNotSet(__privateGet(this, _signer).toSuiAddress());
await __privateGet(this, _buildQueue).runTask(async () => {
const data = transaction.getData();
if (!data.gasData.price) {
transaction.setGasPrice(await __privateMethod(this, _getGasPrice, getGasPrice_fn).call(this));
}
if (!data.gasData.budget) {
transaction.setGasBudget(__privateGet(this, _defaultGasBudget));
}
await __privateMethod(this, _updateCache, updateCache_fn).call(this);
gasCoin = await __privateMethod(this, _getGasCoin, getGasCoin_fn).call(this);
__privateWrapper(this, _pendingTransactions)._++;
transaction.setGasPayment([

@@ -159,5 +197,5 @@ {

]);
transaction.setSenderIfNotSet(__privateGet(this, _signer).toSuiAddress());
return __privateGet(this, _cache).buildTransaction({ transaction });
await __privateGet(this, _cache).buildTransaction({ transaction, onlyTransactionKind: true });
});
const bytes = await transaction.build({ client: __privateGet(this, _client) });
const { signature } = await __privateGet(this, _signer).signTransaction(bytes);

@@ -191,2 +229,3 @@ const results = await __privateGet(this, _cache).executeTransaction({

}
__privateSet(this, _lastDigest, results.digest);
return {

@@ -203,3 +242,8 @@ digest: results.digest,

}
await __privateGet(this, _cache).cache.deleteObjects([...usedObjects]);
await __privateMethod(this, _updateCache, updateCache_fn).call(this, async () => {
await Promise.all([
__privateGet(this, _cache).cache.deleteObjects([...usedObjects]),
__privateMethod(this, _waitForLastDigest, waitForLastDigest_fn).call(this)
]);
});
throw error;

@@ -215,7 +259,29 @@ } finally {

});
__privateWrapper(this, _pendingTransactions)._--;
}
};
_updateCache = new WeakSet();
updateCache_fn = async function(fn) {
if (__privateGet(this, _cacheLock)) {
await __privateGet(this, _cacheLock);
}
__privateSet(this, _cacheLock, fn?.().then(
() => {
__privateSet(this, _cacheLock, null);
},
() => {
}
) ?? null);
};
_waitForLastDigest = new WeakSet();
waitForLastDigest_fn = async function() {
const digest = __privateGet(this, _lastDigest);
if (digest) {
__privateSet(this, _lastDigest, null);
await __privateGet(this, _client).waitForTransaction({ digest });
}
};
_getGasCoin = new WeakSet();
getGasCoin_fn = async function() {
if (__privateGet(this, _coinPool).length === 0 && __privateGet(this, _executeQueue).activeTasks <= __privateGet(this, _maxPoolSize)) {
if (__privateGet(this, _coinPool).length === 0 && __privateGet(this, _pendingTransactions) <= __privateGet(this, _maxPoolSize)) {
await __privateMethod(this, _refillCoinPool, refillCoinPool_fn).call(this);

@@ -229,2 +295,22 @@ }

};
_getGasPrice = new WeakSet();
getGasPrice_fn = async function() {
const remaining = __privateGet(this, _gasPrice) ? __privateGet(this, _gasPrice).expiration - __privateGet(this, _epochBoundaryWindow) - Date.now() : 0;
if (remaining > 0) {
return __privateGet(this, _gasPrice).price;
}
if (__privateGet(this, _gasPrice)) {
const timeToNextEpoch = Math.max(
__privateGet(this, _gasPrice).expiration + __privateGet(this, _epochBoundaryWindow) - Date.now(),
1e3
);
await new Promise((resolve) => setTimeout(resolve, timeToNextEpoch));
}
const state = await __privateGet(this, _client).getLatestSuiSystemState();
__privateSet(this, _gasPrice, {
price: BigInt(state.referenceGasPrice),
expiration: Number.parseInt(state.epochStartTimestampMs, 10) + Number.parseInt(state.epochDurationMs, 10)
});
return __privateMethod(this, _getGasPrice, getGasPrice_fn).call(this);
};
_refillCoinPool = new WeakSet();

@@ -234,3 +320,3 @@ refillCoinPool_fn = async function() {

__privateGet(this, _coinBatchSize),
__privateGet(this, _maxPoolSize) - (__privateGet(this, _coinPool).length + __privateGet(this, _executeQueue).activeTasks) + 1
__privateGet(this, _maxPoolSize) - (__privateGet(this, _coinPool).length + __privateGet(this, _pendingTransactions)) + 1
);

@@ -275,2 +361,3 @@ if (batchSize === 0) {

txb.transferObjects(coinResults, address);
await __privateMethod(this, _updateCache, updateCache_fn).call(this, () => __privateMethod(this, _waitForLastDigest, waitForLastDigest_fn).call(this));
const result = await __privateGet(this, _client).signAndExecuteTransaction({

@@ -277,0 +364,0 @@ transaction: txb,

@@ -14,3 +14,3 @@ import { bcs } from '../../bcs/index.js';

buildTransaction(transaction: Transaction): Promise<Uint8Array>;
resetCache(): Promise<void>;
resetCache(): Promise<[void, void]>;
executeTransaction(transaction: Transaction | Uint8Array): Promise<{

@@ -17,0 +17,0 @@ digest: string;

@@ -19,3 +19,7 @@ var __accessCheck = (obj, member, msg) => {

};
var _queue, _signer, _cache, _cacheGasCoin, _buildTransaction;
var __privateMethod = (obj, member, method) => {
__accessCheck(obj, member, "access private method");
return method;
};
var _queue, _signer, _cache, _client, _lastDigest, _cacheGasCoin, _buildTransaction, _waitForLastTransaction, waitForLastTransaction_fn;
import { toB64 } from "@mysten/bcs";

@@ -31,5 +35,8 @@ import { bcs } from "../../bcs/index.js";

}) {
__privateAdd(this, _waitForLastTransaction);
__privateAdd(this, _queue, new SerialQueue());
__privateAdd(this, _signer, void 0);
__privateAdd(this, _cache, void 0);
__privateAdd(this, _client, void 0);
__privateAdd(this, _lastDigest, null);
__privateAdd(this, _cacheGasCoin, async (effects) => {

@@ -56,2 +63,3 @@ if (!effects.V2) {

__privateSet(this, _signer, signer);
__privateSet(this, _client, options.client);
__privateSet(this, _cache, new CachingTransactionExecutor({

@@ -69,3 +77,3 @@ client: options.client,

resetCache() {
return __privateGet(this, _cache).reset();
return Promise.all([__privateGet(this, _cache).reset(), __privateMethod(this, _waitForLastTransaction, waitForLastTransaction_fn).call(this)]);
}

@@ -86,2 +94,3 @@ executeTransaction(transaction) {

await this.applyEffects(effects);
__privateSet(this, _lastDigest, results.digest);
return {

@@ -97,4 +106,13 @@ digest: results.digest,

_cache = new WeakMap();
_client = new WeakMap();
_lastDigest = new WeakMap();
_cacheGasCoin = new WeakMap();
_buildTransaction = new WeakMap();
_waitForLastTransaction = new WeakSet();
waitForLastTransaction_fn = async function() {
if (__privateGet(this, _lastDigest)) {
await __privateGet(this, _client).waitForTransaction({ digest: __privateGet(this, _lastDigest) });
__privateSet(this, _lastDigest, null);
}
};
function getGasCoinFromEffects(effects) {

@@ -101,0 +119,0 @@ if (!effects.V2) {

@@ -80,3 +80,3 @@ import { parse } from "valibot";

const objectsToResolve = transactionData.inputs.filter((input) => {
return input.UnresolvedObject && !input.UnresolvedObject.version || input.UnresolvedObject?.initialSharedVersion;
return input.UnresolvedObject && !(input.UnresolvedObject.version || input.UnresolvedObject?.initialSharedVersion);
});

@@ -102,3 +102,3 @@ const dedupedIds = [

);
const invalidObjects = Array.from(responsesById).filter(([_, obj]) => obj.error).map(([id, _obj]) => id);
const invalidObjects = Array.from(responsesById).filter(([_, obj]) => obj.error).map(([_, obj]) => JSON.stringify(obj.error));
if (invalidObjects.length) {

@@ -132,6 +132,6 @@ throw new Error(`The following input objects are invalid: ${invalidObjects.join(", ")}`);

const object = objectsById.get(id);
if (object?.initialSharedVersion) {
if (input.UnresolvedObject.initialSharedVersion ?? object?.initialSharedVersion) {
updated = Inputs.SharedObjectRef({
objectId: id,
initialSharedVersion: object.initialSharedVersion,
initialSharedVersion: input.UnresolvedObject.initialSharedVersion || object?.initialSharedVersion,
mutable: isUsedAsMutable(transactionData, index)

@@ -138,0 +138,0 @@ });

@@ -129,9 +129,10 @@ var __accessCheck = (obj, member, msg) => {

input.UnresolvedObject.initialSharedVersion = cached2.initialSharedVersion;
} else {
if (cached2.version && !input.UnresolvedObject.version) {
input.UnresolvedObject.version = cached2.version;
}
if (cached2.digest && !input.UnresolvedObject.digest) {
input.UnresolvedObject.digest = cached2.digest;
}
}
if (cached2.version && !input.UnresolvedObject.version) {
input.UnresolvedObject.version = cached2.version;
}
if (cached2.digest && !input.UnresolvedObject.digest) {
input.UnresolvedObject.digest = cached2.digest;
}
}

@@ -138,0 +139,0 @@ await Promise.all(

@@ -1,2 +0,2 @@

export declare const PACKAGE_VERSION = "0.0.0-experimental-20240614013711";
export declare const PACKAGE_VERSION = "0.0.0-experimental-20240621004420";
export declare const TARGETED_RPC_VERSION = "1.28.0";

@@ -1,2 +0,2 @@

const PACKAGE_VERSION = "0.0.0-experimental-20240614013711";
const PACKAGE_VERSION = "0.0.0-experimental-20240621004420";
const TARGETED_RPC_VERSION = "1.28.0";

@@ -3,0 +3,0 @@ export {

@@ -6,3 +6,3 @@ {

"homepage": "https://sdk.mystenlabs.com",
"version": "0.0.0-experimental-20240614013711",
"version": "0.0.0-experimental-20240621004420",
"license": "Apache-2.0",

@@ -9,0 +9,0 @@ "sideEffects": false,

@@ -7,2 +7,3 @@ // Copyright (c) Mysten Labs, Inc.

import type { Signer } from '../../cryptography/keypair.js';
import type { BuildTransactionOptions } from '../json-rpc-resolver.js';
import type { ObjectCacheOptions } from '../ObjectCache.js';

@@ -36,6 +37,10 @@ import { ObjectCache } from '../ObjectCache.js';

async buildTransaction({ transaction }: { transaction: Transaction }) {
async buildTransaction({
transaction,
...options
}: { transaction: Transaction } & BuildTransactionOptions) {
transaction.addBuildPlugin(this.cache.asPlugin());
return transaction.build({
client: this.#client,
...options,
});

@@ -42,0 +47,0 @@ }

@@ -21,2 +21,3 @@ // Copyright (c) Mysten Labs, Inc.

maxPoolSize: 50,
epochBoundaryWindow: 1_000,
} satisfies Omit<ParallelTransactionExecutorOptions, 'signer' | 'client'>;

@@ -26,6 +27,19 @@ export interface ParallelTransactionExecutorOptions extends Omit<ObjectCacheOptions, 'address'> {

signer: Signer;
/** The number of coins to create in a batch when refilling the gas pool */
coinBatchSize?: number;
/** The initial balance of each coin created for the gas pool */
initialCoinBalance?: bigint;
/** The minimum balance of a coin that can be reused for future transactions. If the gasCoin is below this value, it will be used when refilling the gasPool */
minimumCoinBalance?: bigint;
/** The gasBudget to use if the transaction has not defined it's own gasBudget, defaults to `minimumCoinBalance` */
defaultGasBudget?: bigint;
/**
* Time to wait before/after the expected epoch boundary before re-fetching the gas pool (in milliseconds).
* Building transactions will be paused for up to 2x this duration around each epoch boundary to ensure the
* gas price is up-to-date for the next epoch.
* */
epochBoundaryWindow?: number;
/** The maximum number of transactions that can be execute in parallel, this also determines the maximum number of gas coins that will be created */
maxPoolSize?: number;
/** An initial list of coins used to fund the gas pool, uses all owned SUI coins by default */
sourceCoins?: string[];

@@ -46,2 +60,4 @@ }

#minimumCoinBalance: bigint;
#epochBoundaryWindow: number;
#defaultGasBudget: bigint;
#maxPoolSize: number;

@@ -54,2 +70,9 @@ #sourceCoins: Map<string, SuiObjectRef | null> | null;

#executeQueue: ParallelQueue;
#lastDigest: string | null = null;
#cacheLock: Promise<void> | null = null;
#pendingTransactions = 0;
#gasPrice: null | {
price: bigint;
expiration: number;
} = null;

@@ -64,2 +87,5 @@ constructor(options: ParallelTransactionExecutorOptions) {

options.minimumCoinBalance ?? PARALLEL_EXECUTOR_DEFAULTS.minimumCoinBalance;
this.#defaultGasBudget = options.defaultGasBudget ?? this.#minimumCoinBalance;
this.#epochBoundaryWindow =
options.epochBoundaryWindow ?? PARALLEL_EXECUTOR_DEFAULTS.epochBoundaryWindow;
this.#maxPoolSize = options.maxPoolSize ?? PARALLEL_EXECUTOR_DEFAULTS.maxPoolSize;

@@ -77,3 +103,4 @@ this.#cache = new CachingTransactionExecutor({

resetCache() {
return this.#cache.reset();
this.#gasPrice = null;
return this.#updateCache(() => this.#cache.reset());
}

@@ -154,4 +181,18 @@

try {
const bytes = await this.#buildQueue.runTask(async () => {
transaction.setSenderIfNotSet(this.#signer.toSuiAddress());
await this.#buildQueue.runTask(async () => {
const data = transaction.getData();
if (!data.gasData.price) {
transaction.setGasPrice(await this.#getGasPrice());
}
if (!data.gasData.budget) {
transaction.setGasBudget(this.#defaultGasBudget);
}
await this.#updateCache();
gasCoin = await this.#getGasCoin();
this.#pendingTransactions++;
transaction.setGasPayment([

@@ -164,7 +205,9 @@ {

]);
transaction.setSenderIfNotSet(this.#signer.toSuiAddress());
return this.#cache.buildTransaction({ transaction: transaction });
// Resolve cached references
await this.#cache.buildTransaction({ transaction, onlyTransactionKind: true });
});
const bytes = await transaction.build({ client: this.#client });
const { signature } = await this.#signer.signTransaction(bytes);

@@ -208,2 +251,4 @@

this.#lastDigest = results.digest;
return {

@@ -222,3 +267,9 @@ digest: results.digest,

await this.#cache.cache.deleteObjects([...usedObjects]);
await this.#updateCache(async () => {
await Promise.all([
this.#cache.cache.deleteObjects([...usedObjects]),
this.#waitForLastDigest(),
]);
});
throw error;

@@ -234,7 +285,31 @@ } finally {

});
this.#pendingTransactions--;
}
}
/** Helper for synchronizing cache updates, by ensuring only one update happens at a time. This can also be used to wait for any pending cache updates */
async #updateCache(fn?: () => Promise<void>) {
if (this.#cacheLock) {
await this.#cacheLock;
}
this.#cacheLock =
fn?.().then(
() => {
this.#cacheLock = null;
},
() => {},
) ?? null;
}
async #waitForLastDigest() {
const digest = this.#lastDigest;
if (digest) {
this.#lastDigest = null;
await this.#client.waitForTransaction({ digest });
}
}
async #getGasCoin() {
if (this.#coinPool.length === 0 && this.#executeQueue.activeTasks <= this.#maxPoolSize) {
if (this.#coinPool.length === 0 && this.#pendingTransactions <= this.#maxPoolSize) {
await this.#refillCoinPool();

@@ -251,6 +326,36 @@ }

async #getGasPrice(): Promise<bigint> {
const remaining = this.#gasPrice
? this.#gasPrice.expiration - this.#epochBoundaryWindow - Date.now()
: 0;
if (remaining > 0) {
return this.#gasPrice!.price;
}
if (this.#gasPrice) {
const timeToNextEpoch = Math.max(
this.#gasPrice.expiration + this.#epochBoundaryWindow - Date.now(),
1_000,
);
await new Promise((resolve) => setTimeout(resolve, timeToNextEpoch));
}
const state = await this.#client.getLatestSuiSystemState();
this.#gasPrice = {
price: BigInt(state.referenceGasPrice),
expiration:
Number.parseInt(state.epochStartTimestampMs, 10) +
Number.parseInt(state.epochDurationMs, 10),
};
return this.#getGasPrice();
}
async #refillCoinPool() {
const batchSize = Math.min(
this.#coinBatchSize,
this.#maxPoolSize - (this.#coinPool.length + this.#executeQueue.activeTasks) + 1,
this.#maxPoolSize - (this.#coinPool.length + this.#pendingTransactions) + 1,
);

@@ -304,2 +409,4 @@

await this.#updateCache(() => this.#waitForLastDigest());
const result = await this.#client.signAndExecuteTransaction({

@@ -306,0 +413,0 @@ transaction: txb,

@@ -18,2 +18,4 @@ // Copyright (c) Mysten Labs, Inc.

#cache: CachingTransactionExecutor;
#client: SuiClient;
#lastDigest: string | null = null;

@@ -28,2 +30,3 @@ constructor({

this.#signer = signer;
this.#client = options.client;
this.#cache = new CachingTransactionExecutor({

@@ -74,5 +77,12 @@ client: options.client,

resetCache() {
return this.#cache.reset();
return Promise.all([this.#cache.reset(), this.#waitForLastTransaction()]);
}
async #waitForLastTransaction() {
if (this.#lastDigest) {
await this.#client.waitForTransaction({ digest: this.#lastDigest });
this.#lastDigest = null;
}
}
executeTransaction(transaction: Transaction | Uint8Array) {

@@ -98,2 +108,3 @@ return this.#queue.runTask(async () => {

await this.applyEffects(effects);
this.#lastDigest = results.digest;

@@ -100,0 +111,0 @@ return {

@@ -151,4 +151,4 @@ // Copyright (c) Mysten Labs, Inc.

return (
(input.UnresolvedObject && !input.UnresolvedObject.version) ||
input.UnresolvedObject?.initialSharedVersion
input.UnresolvedObject &&
!(input.UnresolvedObject.version || input.UnresolvedObject?.initialSharedVersion)
);

@@ -183,3 +183,3 @@ }) as Extract<CallArg, { UnresolvedObject: unknown }>[];

.filter(([_, obj]) => obj.error)
.map(([id, _obj]) => id);
.map(([_, obj]) => JSON.stringify(obj.error));

@@ -223,6 +223,7 @@ if (invalidObjects.length) {

if (object?.initialSharedVersion) {
if (input.UnresolvedObject.initialSharedVersion ?? object?.initialSharedVersion) {
updated = Inputs.SharedObjectRef({
objectId: id,
initialSharedVersion: object.initialSharedVersion,
initialSharedVersion:
input.UnresolvedObject.initialSharedVersion || object?.initialSharedVersion!,
mutable: isUsedAsMutable(transactionData, index),

@@ -229,0 +230,0 @@ });

@@ -185,11 +185,11 @@ // Copyright (c) Mysten Labs, Inc.

input.UnresolvedObject.initialSharedVersion = cached.initialSharedVersion;
}
} else {
if (cached.version && !input.UnresolvedObject.version) {
input.UnresolvedObject.version = cached.version;
}
if (cached.version && !input.UnresolvedObject.version) {
input.UnresolvedObject.version = cached.version;
if (cached.digest && !input.UnresolvedObject.digest) {
input.UnresolvedObject.digest = cached.digest;
}
}
if (cached.digest && !input.UnresolvedObject.digest) {
input.UnresolvedObject.digest = cached.digest;
}
}

@@ -196,0 +196,0 @@

@@ -6,3 +6,3 @@ // Copyright (c) Mysten Labs, Inc.

export const PACKAGE_VERSION = '0.0.0-experimental-20240614013711';
export const PACKAGE_VERSION = '0.0.0-experimental-20240621004420';
export const TARGETED_RPC_VERSION = '1.28.0';

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc