Repository navigation
This release supports Supra node v11.7.2, which runs on Mainnet and Testnet, and the v12.0.0 release candidates, which run on Devnet. compatibility.json lists the node releases that each SDK release supports. Entries marked Breaking: change behaviour or types that code written for 1.2.0 can depend on; MIGRATION.md describes what to change for each of them.
Symbols that wrap the node API added in supra_node_v12.0.0 are tagged @beta: getAccountHistory, viewBatch, getTransactionsByHashes, simulate.withStateChanges, getSettlements, getSettlement, getNativeSupply, the settlement transaction response types, the Remove variant of AutomationRecordAction, NodeVersionInfo.release, and the types only they use. Generic-view conversion with type arguments other than address and sponsoring a sender with no account follow the same rule. These are exempt from semantic versioning until supra_node_v12.0.0 reaches Testnet, so a 2.x minor release can change them; a minor release removes the tags after that. See the README section "Stability".
Added
Network.DEVNET—new SupraClient({ network: Network.DEVNET })connects tohttps://rpc-devnet.supra.comwith chain ID 50. TheSupraConfigtype accepts it alongsideNetwork.MAINNETandNetwork.TESTNET.SupraFaucetUnavailableError— thrown byfundAccountWithFaucetwhen the node answers"TryLater"because no faucet account is free.SupraFaucetResponseErroris thrown when the node answers with any other body that carries no transaction hash; the body is available asdata.supra.getNodeVersion()— readsGET /rpc/v3/versionand returns{ version, release?, branch, commit_hash, build_time, build_env }(typeNodeVersionInfo).releaseis the node release tag, for examplesupra_node_v12.0.0.rc7; it is absent from the response of a node older thansupra_node_v12.0.0, so it isundefinedfor a v11 node.faucet.getFaucetTransaction({ transactionHash })— reads a faucet transaction (GET /rpc/v3/wallet/faucet/transactions/{hash}).- Typed errors.
SupraNotFoundError(HTTP 404),SupraGoneError(410, witholdestBlock, the oldest block the node holds, from thex-supra-oldest-blockheader;undefinedwhen the header is absent or malformed),SupraRateLimitError(429, withretryAfterSecondsfrom the body'sretry_after_secondsor theRetry-Afterheader) andSupraServiceUnavailableError(503) extendSupraAPIError, soinstanceof SupraAPIErrorstill matches.SupraTimeoutErrorandSupraNetworkErrorare thrown for a request that times out or fails before the node answers; the original error is theircause. For a submission request they are thecauseofSupraSubmissionOutcomeUnknownError(below).SupraErroris the base class of all of them and of the faucet errors. SupraAPIError.sub_statusis the abort code of anABORTEDstatus.parseVmStatusis exported.MoveVmErrorlists the validation, verification, invariant and runtime statuses that clients commonly handle, includingABORTED,MISSING_DATA,TYPE_RESOLUTION_FAILURE,LOOKUP_FAILEDandMAX_GAS_UNITS_*.- Transaction outcome errors.
SupraTransactionFailedError(a transaction the SDK waited for ended withFailorInvalid; carrieshash,status,vm_status,major_status,sub_statusandtransaction),SupraSimulationFailedError(a simulation returned a status other thanSuccess; carriesstatus,vm_status,major_status,sub_statusandtransaction) andSupraTransactionTimeoutError(no final status within the wait timeout; carrieshash,timeoutMs,lastStatus,transactionand the last read error ascause). All three extendSupraError. SupraSubmissionOutcomeUnknownError(extendsSupraError; carrieshash,sender,sequenceNumber,expirationTimestampSecs,waitError,readStatus,readError, and the error of the request ascause; thereadfields are set after a v11.7Already scheduledrefusal, see Fixed) is thrown by every submit helper when the submission request times out (SupraTimeoutError), fails before the node answers (SupraNetworkError), or is answered with a 5xx status other than 503 (SupraAPIError). In each case the node may have accepted the transaction; lookhashup or wait for it before sending the transaction again. The submit helpers derive the hash from the signed transaction before they submit it (the Keccak-256 of its BCS bytes, asderiveTransactionHashdoes), which is the hash v11.7.0 and v12 nodes give a transaction of every kind the SDK submits. WithenableWaitForTransaction, the helper first waits for that hash within the wait timeout: a transaction that reaches a final status is returned, or throwsSupraTransactionFailedError, as after an accepted submission, and the error is thrown, with the wait'sSupraTransactionTimeoutErroraswaitError, when the wait ends without a final status. A refusal of the node (a 4xx status or 503) is thrown as aSupraAPIError, or asSupraGasUnitPriceBelowMinimumErrorwhen the gas unit price is below the node's minimum (below).FixedPoint32andFixedPoint64arguments. An entry or view function parameter of type0x1::fixed_point32::FixedPoint32or0x1::fixed_point64::FixedPoint64, also insidevectorandOption, takes the struct's rawu64oru128value as abigintor a decimal string, with the range checks ofu64andu128.transaction.build.simplepreviously threwUnsupported typefor them.MoveToTSmaps them tobigint | string.SubmitTransactionResponseandNotReadBackTransactionResponsetypes.SupraConfig.waitTimeoutMssets how longwaitForTransactionand submissions withenableWaitForTransactionwait for a final status (defaultDEFAULT_TXN_WAIT_TIMEOUT_MS, 60000 ms).enableTransactionWaitAndSimulationArgs.waitTimeoutMsandcheckSuccessset the wait timeout of one submission and whether aFailorInvalidoutcome throws (default true).WaitForTransactionOptions.timeoutMssets the wait timeout of onewaitForTransactioncall in milliseconds.timeoutSecsis deprecated and still honoured;timeoutMstakes precedence.- Max gas estimate. Without a
maxGason the call or the client, the coin and fungible asset transfers,publishPackage, the automation task helpers, the multisig helpers and the entry functions ofContract.fromABIread the sender's SUPRA balance, simulate the transaction with the largest max gas that balance pays for (at mostMAX_GAS_UNITS_PER_TRANSACTION), and submit it withceil(gas used × 1.5), at leastMIN_ESTIMATED_MAX_GAS_UNITS(1,500) and at most what the balance pays for.SupraConfig.maxGasEstimateMultiplierreplaces the factor (DEFAULT_MAX_GAS_ESTIMATE_MULTIPLIER). The simulation runs against committed state: for a transaction sent while earlier transactions of the account that this client submitted have not committed, it uses the account's sequence number on the chain, so pipelined transactions work with the default gas settings; a transaction that depends on an earlier uncommitted one fails its estimate and needsmaxGas. When the simulation reports the number as too new, the estimate reads the account and the latest block. It uses the chain's number when every number between it and the transaction's has a record of a transaction this client submitted (see the counter below); otherwise the transaction is built and signed again with the lowest number that has no record, without giving up its place in the order of the calls. No transaction is read by hash. A failed read of the account is thrown and nothing is submitted. estimateMaxGasinOptionalTransactionPayloadArgsandSupraConfig:falseusesDEFAULT_MAX_GAS_UNITSwithout a request.getEstimatedGasUnitPrice()returns the gas unit price that a transaction carries when neither the call norSupraConfig.gasUnitPricesets one:max(median_gas_price, min_configured_gas_price)ofGET /rpc/v3/transactions/estimate_gas_price. It throws aSupraErrornaming the field whenmedian_gas_priceormin_configured_gas_priceis missing or is not a non-negative integer.SupraGasUnitPriceBelowMinimumError(extendsSupraError) is thrown when the node refuses a submission or a simulation withGAS_UNIT_PRICE_BELOW_MIN_BOUND;gasUnitPriceis the price sent,minimumGasUnitPricethe node's minimum read after the refusal (undefinedwhen that read fails),major_statusthe status name, andcausethe originalSupraAPIErrorof the submission orSupraSimulationFailedErrorof the simulation. The transaction is not sent again and its price is not raised.- Per-account sequence-number counter. Each
SupraClientkeeps, for every account that its helpers send from, the account's sequence number on the chain and a record of each transaction it submitted (accepted, or whose submission request failed without an answer, so the node may have accepted it) with that transaction's expiration time and hash (the node's answer, or for a request without an answer the hash derived from the signed transaction). A transaction the node accepted either commits or, once the timestamp of the latest block has reached its expiration time, can no longer commit. A record is dropped when the chain's number passes it, when the timestamp of a latest block the client reads (GET /rpc/v3/block; not a block read by height or hash) has reached its expiration time, or when a read of the transaction returnsInvalid(the next call then reads the account's number from the chain, since another sender may have committed the number); an HTTP 404 does not drop it, since an RPC node answers 404 for a pending transaction that another RPC node received. A submission whose outcome is unknown holds its number until the transaction's expiration time orresetSequenceNumber, including when its expiration time was beyond what a node accepts. The next number is the lowest number at or above the chain's that has no record. The first use reads the account and the latest block; so does the next call after a refusal for a stale number or a full queue, and every call (once per call) while the estimated chain time has passed the expiration time of a record by two seconds and no latest block read has reached it. The estimated chain time is the newest latest block's timestamp read plus the time elapsed since that read on a monotonic clock (performance.now()); it does not depend on the client's wall clock and does not move backwards. A read never drops a record that can still commit. A check behind pending transactions uses the higher of the account's number read and the highest number the client has observed on the chain. A refusal for a stale number (SEQUENCE_NUMBER_TOO_OLD,SEQUENCE_NUMBER_TOO_NEW, a number below the account's, or a number that already has a pending transaction) makes the helper send the transaction once more with the next number. A helper call that takes its number from the counter does not deduplicate: a repeated call, including one from a restarted process that builds the same transaction again, submits a new transaction; when the node already holds the same transaction, its number stays recorded and the helper sends its transaction with the next number. A helper call with an explicitsequenceNumberwhose transaction the node already holds is handled as the submit methods handle it (see Fixed). A transaction refused for another reason has no record, and the next call uses its number. Transactions with an explicitsequenceNumberare recorded as well. After a submission whose outcome is unknown that the node did not accept, later calls wait behind its number in the node until the chain's time reaches its expiration time, and the next call then takes that number. Calls of one client from one account are submitted one after another: a call holds the account from taking its number until the node answers its submission, and the wait for the final status comes after that. A call withoutmaxGasholds the account while its max gas is estimated; a call withmaxGaswaits only until the calls ahead of it have been submitted or have failed. Concurrent sends from one account get consecutive numbers. To submit faster, setmaxGasor send from several accounts. A call with an explicitsequenceNumberdoes not take part in this order. SupraClient.resetSequenceNumber(address)forgets the counter of an account and its records of the client's transactions; the next transaction reads its number from the chain. While a transaction of this client from the account is pending, the node refuses the next helper call, whose number that transaction holds; reset when none is pending or their expiration times have passed.SupraAccountQueueFullError(extendsSupraAPIError; carriessequenceNumber) is thrown when the node refuses a submission whose sequence number is beyond the numbers it queues for the account ahead of the chain's (25 by default). The helpers do not send it again; the next call reads the chain before it takes a number.SupraConfig.txExpirySecssets how many seconds after the client's clock (in whole seconds) a transaction built withouttxExpiryTimeexpires: a positive integer, defaultDEFAULT_TX_EXPIRATION_DURATION(60). The expiration time is at mostTX_EXPIRATION_MARGIN_SECS(5) seconds less than the node's maximum time to live after the client's clock, so that a node whose clock is up to 5 seconds behind the client's accepts it. A builder that sends requests throws aRangeErrorwhentxExpirySecsis more than the node's maximum.getTransactionParameters()readsGET /rpc/v3/transactions/parametersand returns{ max_transaction_time_to_live_seconds }, the most seconds after the node's clock that the node accepts as a transaction's expiration time (600 on Mainnet, Testnet and Devnet). The client reads it once, when a builder that sends requests or a signature first needs it, and keeps it;getTransactionParameters()reads it again and the client uses the new value. A failed read throws its error and is not kept: there is no fallback to 600. Signing throws aRangeErrorbefore signing when a transaction's expiration time, whoever set it, is more than the node's maximum after the later of the client's clock and the chain time estimated from the client's reads of the latest block, allowingTX_EXPIRATION_MARGIN_SECS(5) seconds of slack because that estimate can trail the node's clock; withverifyChainId: falsesigning sends no request and does not check it. The builders that send no request (rawTxnObjectand the like) use the maximum the client has read, elseASSUMED_MAX_TX_EXPIRATION_DURATION(600), and throw aRangeErrorwhentxExpirySecsis more than it. The messages of theseRangeErrors name the maximum and say whether it was read from the node or assumed; for an assumed one they namegetTransactionParameters().OptionalTransactionPayloadArgs.sequenceNumbersets the sequence number of a transaction built bycoin.transferSupraCoin,coin.transferCoin,fungibleAsset.transferSupraFungibleAsset,fungibleAsset.transferFungibleAsset,fungibleAsset.migrateCoinToFungibleStore,transaction.publishPackage,automation.cancelAutomationTask,automation.stopAutomationTasks, the multisig helpers and the entry functions ofContract.fromABI. The helper uses it as given and does not take part in the order of the calls; the counter records the submitted transaction like its own and does not hand out its number while it can commit.- Chain ID check before signing. Before its first signature a client reads the chain ID of its node, from the
x-supra-chain-idheader of an earlier response or withGET /rpc/v3/transactions/chain_id, and keeps it for its lifetime; concurrent first signatures share one request. Every signing path (signTransaction, the signing methods oftransaction.buildand of a built transaction, thetransaction.submitmethods that take asenderAccount, the coin and fungible asset transfers,publishPackage, the automation task helpers, the multisig helpers and the entry functions ofContract.fromABI) throwsSupraChainIdMismatchError(extendsSupraError; carriesconfiguredChainId,nodeChainIdandtransactionChainId) before signing when the configured chain ID or the transaction's chain ID is not the node's. SupraConfig.verifyChainId:falseturns the check off for offline signing. The client signs with its configured chain ID and sends no request to do so.parseTypeArgumentis exported. It parses a Move type string into aTypeTagwith the grammar of the node's type parser, as the SDK does for type argument strings:0x1::object::Object<T>stays the structObject<T>, and names that containTfollowed by digits are accepted. Use it for theTypeTags oftransaction.build.rawTxnObjectand the other builders that takeTypeTags, whereTypeTagParserturnsObject<T>intoaddress.stringifyWithBigIntis exported. It serializes a value whosebigintfields (for example the result oftransaction.build.sendTxnPayload)JSON.stringifyrejects, writing them as exact JSON numbers.- Settlement transactions, returned by nodes from v12 onwards:
TransactionType.Settlement, theSettlementTransactionResponsevariant ofCommittedTransactionResponseandTransactionResponse(withSettlementData,SettlementApplierSummary,SettlementCreditSummaryandAppliedInboundSettlement), and"settlement"inTransactionQueryType. A settlement item has noheader,payloadorauthenticator.SettlementApplierSummary.burn_amount(quants) is abigint, exact aboveNumber.MAX_SAFE_INTEGER, on every read that returns transactions. AutomationTransactionResponse.predicate(AutomationPredicateInfo), theRemovevariant ofAutomationRecordAction(itskindis"Error","ConfigUpdate"or"PreExecutionLimit"),EvmTransactionOutputinTransactionOutput, and the v12 fields andautomation_record_countofExecutedBlockStatistics, the type ofFinalizedBlockHeader.execution_statistics.evm_base_fee_per_gasisbigint | null, exact aboveNumber.MAX_SAFE_INTEGER.getAccountTransactionsreturns acursor: the sequence number after the last transaction of the page in the requested order, so the feed is read to its end like the others. Itsstartalso accepts anumberorbigint.account.getPrimaryStoreAddress({ accountAddress, metadataAddress? })returns the address of an account's primary fungible store for a fungible asset (default SUPRA,0xa) with0x1::primary_fungible_store::primary_store_address.account.getAccountFaTransactions({ storeAddress, options? })readsGET /rpc/v3/accounts/{address}/fa_transactions: the finalized transactions that withdrew from or deposited to one fungible store.storeAddressis the store's address, for example fromgetPrimaryStoreAddress; an account address returns an empty page.getAccountHistorylists everything that concerns an account.optionsarecount,start,ascendingandtype. Mainnet, Testnet and Devnet nodes serve the route. The feed ends likegetAccountCoinTransactions:cursorisundefinedwhen the header is absent or empty, or on an empty page with the cursor"0", except for the first request of an ascending read with atypefilter (see the change toPaginatedResponse.cursorbelow).account.getAccountHistory({ accountAddress, options? })readsGET /rpc/v3/accounts/{address}/history, which nodes fromsupra_node_v12.0.0serve (Devnet): every finalized transaction that concerns the account, once each, as{ categories, transaction }entries (AccountHistoryEntry).optionsarecategories(a non-empty subset of"sent","coin","fa"and"da", default all four),count,ascendingandstart. The feed ends only when a response has nox-supra-cursorheader: an empty page that carries a cursor, and the cursor"0", do not end it. The page (AccountHistoryPage) also carriesindexedFrom(x-supra-history-indexed-from, the lowest block height the history covers) andoldestBlock(x-supra-oldest-block). The history omits automated transactions and automation records; read them withgetAccountAutoTransactions. It lists SUPRA transfers between primary fungible stores, whichgetAccountCoinTransactionsdoes not. Mainnet and Testnet nodes at v11.7.x answer HTTP 404, which the method throws asSupraRouteUnsupportedError(extendsSupraNotFoundError; carriesmethodandminimumNodeRelease,"supra_node_v12.0.0").- Operations of the
/rpc/v4API. The client's base path stays/rpc/v3; each of these methods selects/rpc/v4for its own request. All need a node fromsupra_node_v12.0.0(Devnet). On a Mainnet or Testnet node at v11.7.x each route except simulate answers HTTP 404, which the method throws asSupraRouteUnsupportedError(seegetAccountHistory); a 404 ofgetSettlementthat carries the node's JSON error body is the node's answer for an unknown crossing and stays aSupraNotFoundError.methods.viewBatch({ requests })readsPOST /rpc/v4/view/batch: several view functions in one request, executed against one snapshot of Move state. Each element takes the arguments ofview; the SDK reads each module's ABI once for the batch, encodes the arguments and converts each result (u64,u128andu256arebigint). The result is{ state_height, results }, with one{ result }or{ error: { status, message } }entry per element in request order; a failing element does not fail the call, and no exception is thrown for it. Types:ViewBatchResponse,ViewBatchEntry,ViewBatchError.transaction.getTransactionsByHashes({ transactionHashes, type?, exclude_uncommitted?, include_proof? })readsPOST /rpc/v4/transactions/by_hashes. It returns{ transactions, omitted }: one{ hash, transaction }per answered hash in request order,transactionbeingnullfor a hash the node does not know, andomittedthe hashes left out to keep the response within the node's size bound (request them again). The node accepts 1 to 100 hashes by default. Types:TransactionsByHashesResponse,TransactionByHashesEntry,TransactionResponseV4,TransactionInclusionProof.MoveEventgains the optionalhashthat the/rpc/v4routes send.transaction.simulate.withStateChanges({ sendTxPayload })readsPOST /rpc/v4/transactions/simulateand returns the simulated transaction with the changes it would make to Move state:changes(WriteSetChange[]),prior_values(keyed bystate_key_hash),state_height,omitted,omitted_countsandchanges_truncated(TransactionSimulationV4).simulate.simpleandsimulate.serializedare unchanged and keep calling/rpc/v3. A v11.7.x node answers this route as/rpc/v3does: the call succeeds and the six state-change fields are absent from the result, so each is optional in the type.transaction.getSettlements({ address, domain, options? })readsGET /rpc/v4/transactions/settlements: the cross-VM crossings of native SUPRA that an address (domain"move"or"evm") is party to, oldest first, withoptionsrole,countandstart. The page (SettlementsPage) carriescursor, which isundefinedonly on the last page, andoldestBlock.transaction.getSettlement({ settlementId })readsGET /rpc/v4/transactions/settlements/{settlement_id}: every stage of one crossing, its queue entry while it is pending, and the height the node had executed to (Settlement). A crossing recorded below the node's oldest retained block throwsSupraGoneError.amountofPendingSettlementandSettlementStageEntry(quants) is abigint.fungibleAsset.getNativeSupply()readsGET /rpc/v4/supply/native: native SUPRA on SupraEVM, the value in flight between the two VMs, and the SupraMVM escrow backing it, as of one height (NativeSupply).burn_owed_quantsandescrow_settled_quantsarebigintandescrow_balance_quantsisbigint | null; the wei figures are decimal strings.- A
u64that the node sends as a JSON number and that can exceedNumber.MAX_SAFE_INTEGERis read exactly, from the number form and from the decimal string form that a later node release sends: the fields above andevm_base_fee_per_gas. Other numbers in a response are parsed as before.
SupraConfig.timeoutMssets the request timeout (default 30000 ms; an integer up to 2147483647) for predefined networks and custom configurations.SupraConfig.retry({ attempts, maxDelayMs },maxDelayMsup to 2147483647) turns on retries of GET requests that fail with 429, 503 or a connection failure, honouring the node'sretry_after_seconds/Retry-After. It is off by default; POST requests and the faucet request are never retried.fungibleAsset.migrateCoinToFungibleStore({ senderAccount, coinType?, optionalTransactionArgs? })submits0x1::coin::migrate_to_fungible_store, which moves the sender's balance of a coin type (default SUPRA) from itsCoinStoreto the primary fungible store of the paired fungible asset.SupraInsufficientFungibleAssetBalanceError(senderAddress,assetAddress,amount,fungibleAssetBalance,coinBalance), thrown by the SUPRA fungible asset transfers described under Changed.account.getAccountSupraBalancereturns{ total, coin, fungibleAsset }(SupraBalance): the SUPRA balance in quants and the parts held in theCoinStoreand in the fungible asset store.SUPRA_FUNGIBLE_ASSET_ADDRESSis the address of the SUPRA fungible asset (0xa, padded to 64 digits).pnpm examplesruns every example inexamples/against the network thatSUPRA_RPC_URL/SUPRA_CHAIN_IDorSUPRA_NETWORKnames (default Devnet);SUPRA_EXAMPLES_FUND=1funds their accounts from that node's faucet. The examples create or query the data they need instead of using hard-coded hashes, heights and Testnet addresses. CI type-checks the examples, and a scheduled workflow runs them on Devnet.- README sections on reading a feed page by page and on the HTTP status codes that differ between v11 and v12 nodes.
pnpm check:jsdoctype-checks the```typescriptblocks of the JSDoc undersrc/, ofSKILL.mdand ofMIGRATION.mdagainstsrc/index.ts; CI runs it with the lint and type-check steps.MIGRATION.mdlists the breaking changes from 1.2.0 to 2.0.0 and the code to change for each.compatibility.jsonlists, for each SDK release, the node releases it supports and the RPC API versions it calls. A unit test checks that its latest release is the version inpackage.json. The package ships it, readable assupra-ts-sdk/compatibility.json.RELEASING.mddescribes the versioning policy, the npm dist-tags and the release checklist.- The types that public signatures reference are exported:
ExtendedRawTransaction(returned by theBuildmethods),FixedPointTypeandMoveToTSOther(used byMoveToTS). - Multisig helpers on
supra.multisigand the client:createMultisigAccount(create_with_owners; returns{ multisigAddress, transaction }, the address derived from the sender and the creating transaction's sequence number),proposeMultisigTransaction(create_transaction, payload stored on chain),proposeMultisigTransactionWithHash(create_transaction_with_hash),approveMultisigTransaction,rejectMultisigTransaction,executeMultisigTransaction,executeRejectedMultisigTransaction, and the readsgetMultisigSequenceNumbers,getMultisigProposalandgetNextMultisigProposal. They use the client's sequence numbers, chain ID check, estimated max gas and hash derivation.executeMultisigTransactionreads the next proposal and sends no payload when the proposal stores it and the call gives none, the call'spayloadwhen it matches the stored one or the stored hash; it throwsSupraMultisigPayloadErrorbefore submitting when a needed payload is missing or does not match, andSupraMultisigNoProposalErrorwhen the queue is empty. The nodes of v11.7.0 and v12.0.0.rc6 do not simulate an execution without a payload (MISSING_DATA), so the max gas estimate andenableTransactionSimulationsimulate it with the stored payload carried, while the transaction that is sent carries none; a stored payload that cannot be decoded throwsSupraMultisigPayloadError(stored-undecodable) when the call needs that simulation. A simulation does not detect missing approvals or an expired proposal.deriveMultisigAccountAddress, the typesMultisigProposal,MultisigVote,MultisigSequenceNumbers,MultisigEntryFunctionPayload,CreateMultisigAccountResponseandMultisigExecutionPayloadArgs, and the constantsDEFAULT_MULTISIG_TIMEOUT_DURATION_SECS(seven days) andMIN_MULTISIG_TIMEOUT_DURATION_SECSare exported. - Automation registrations with version 2 parameters.
transaction.build.automationRegistrationRawTxnObjecttakesautomationTaskType(AutomationTaskType:"User"or"System") andautomationPriority(au64bigint). With either one the registration carries version 2 parameters (RegistrationParamsV2of the node: the version 1 fields followed by the task type and the optional priority); without them it carries version 1 parameters as before. Nodes of the v11.7.0 and v12 lines accept both. A priority belongs to system tasks: the registry aborts a user task that carries one (EUSER_TASK_PRIORITY_NOT_SUPPORTED), so the builder throws aRangeErrorwhenautomationPriorityis given withautomationTaskType: "User"or with no task type. Without a priority the registry uses the task's index as its priority. Only an account that the Supra framework has authorised can register a"System"task.automationGasPriceCapmust be at least the node's minimum gas unit price; the node refuses a lower cap at validation. The submit and simulate methods that take a serialized raw transaction read version 2 parameters.AutomationRegistrationParamV2JSONis the JSON form of the submitted payload. automation.cancelAutomationTask({ senderAccount, taskIndex, optionalTransactionArgs? })submits0x1::automation_registry::cancel_task, andautomation.stopAutomationTasks({ senderAccount, taskIndexes, optionalTransactionArgs? })submits0x1::automation_registry::stop_tasks, for the user automation tasks of the sender. Like the transfers, they take the sequence number from the client's counter and estimate the max gas. TheAutomationclass is also mixed into the client (supra.cancelAutomationTask,supra.stopAutomationTasks).- Sponsored transaction from a sender without an account (documentation). A sender for which
isAccountExistsisfalseuses sequence number 0 inrawTxnObject;getAccountInfothrows for it. A node fromsupra_node_v12.0.0admits the submission and the sender's sequence number is 1 afterwards; a v11.7.x node refuses it with HTTP 400. ThesubmitSponsorTransactionexample, the README and the agent skill show the flow.
Changed
- Breaking: the package requires Node.js 20 or later (
engines.nodeis>=20); 1.2.0 declared>=18. Node.js 18 reached end of life in April 2025, and the CI test matrix no longer includes it. - The package includes a
NOTICEfile, and files with portions derived from@aptos-labs/ts-sdkcarry an Apache-2.0 notice. - Breaking: a view function that returns
0x1::fixed_point32::FixedPoint32or0x1::fixed_point64::FixedPoint64, also insidevectorandOption, returns{ value: bigint }where it returned{ value: string }(the node's JSON). The typed contract proxy types these results with the newMoveResultToTS;ReturnTypesuses it, andMoveToTSno longer maps them to the struct name string. - Breaking:
methods.viewand the contract proxy convert a view argument or result whose type is a type parameter of the function, or contains one (vector<T>,0x1::option::Option<T>, a struct overT), as the type with each type parameter replaced by the call's type argument, as a node fromsupra_node_v12.0.0reads it. They sent and returned such values as given and as the node's JSON. On a v12 node,identity<T>(x: T): Twith the type argumentu64takes abigint(sent as a JSON number and refused by the node in 1.2.0) and returns abigintwhere it returned a string, and with0x1::object::Object<…>returns the address where it returned{ inner }. Arguments are checked against the substituted type before the request:"18446744073709551616"foru64,"300"foru8and"1"forboolthrow, where 1.2.0 sent them. - Breaking: a generic view whose type parameter occurs in a parameter or return type (outside
0x1::object::Object<…>) throwsSupraErrorbefore the view request on a node older thansupra_node_v12.0.0, which reads every type parameter asaddress, unless its type argument isaddressorsigner, or is0x1::object::Object<…>and the type parameter is the whole parameter or return type. To tell, the client readsGET /rpc/v3/versionand keeps areleaseonce the node reports one; after a node without one it reads again on the next such call. Behind a load balancer whose nodes run different releases, the node that answers the version request need not be the node that answers the view. Calls with only address-like type arguments make no version request and behave as in 1.2.0 on a v11 node. In 1.2.0 such a call reached a v11 node, which refused it, or, for a value whose encoding is 32 bytes (au256, for example), read the value's bytes as the type argument and answered with an address-formatted string.methods.viewRawmakes no such check. - Breaking:
fundAccountWithFaucetsends the request on every network, including custom configurations, instead of throwingFaucet is only available on testneton all but Testnet. A node that does not serve the faucet answers with an error status, which is thrown asSupraAPIError. - Breaking:
fundAccountWithFaucetthrowsSupraFaucetUnavailableErrororSupraFaucetResponseErrorwhere it returned{ hash: undefined }. - Breaking:
SupraAPIError.messageis the node'smessagewhen the error body has one (for exampleGeneral err: MoveTransactionValidationFailed(0x…, 0, SEQUENCE_NUMBER_TOO_OLD)), otherwise the HTTP status text. It was always the status text.statusTextanddataare unchanged. - Breaking:
SupraAPIError.major_statusis the name of the Move VM status that the message reports (view errors and submit validation errors), andundefinedwhen the message names none. It was"unknown"for every error.toJSON()also returnsmessageandsub_status. - Breaking:
MoveVmErrorfollows the Move VMStatusCodenames:MOVE_ABORT, which is not a VM status, is removed (ABORTEDreplaces it), the description ofOUT_OF_GASis corrected, and the link to an unrelated repository is removed. - Breaking:
SupraFaucetUnavailableErrorandSupraFaucetResponseErrorextendSupraError; they are still notSupraAPIErrors and keep their names. - Breaking: a request that times out or fails before the node answers, or whose response body cannot be read, rejects with
SupraTimeoutErrororSupraNetworkErrorinstead of a rawDOMExceptionorTypeError. - Breaking: a submission request that times out, fails before the node answers, or is answered with a 5xx status other than 503 makes the submit helper throw
SupraSubmissionOutcomeUnknownErrorwith the error of the request ascause, and withenableWaitForTransactionwait for the derived hash first (see Added). It threw that request'sDOMException,TypeErrororSupraAPIError. This includes the 500 that a v11 node answers when its transaction pool is full. - Breaking: a submission with
enableWaitForTransaction: truethrowsSupraTransactionFailedErrorwhen the transaction ends withFailorInvalid, unlesscheckSuccess: falseis passed. It resolved with the failed transaction. This applies to every submit helper:transaction.submit.*, the submit methods of a built transaction,coin.transferSupraCoin,coin.transferCoin,fungibleAsset.transferSupraFungibleAsset,fungibleAsset.transferFungibleAsset,transaction.publishPackage,automation.cancelAutomationTask,automation.stopAutomationTasks, the multisig helpers and the entry functions ofContract.fromABI. - Breaking: a simulation throws
SupraSimulationFailedErrorfor every status other thanSuccess, includingPendingAfterExecution(for exampleSENDING_ACCOUNT_DOES_NOT_EXISTorSEQUENCE_NUMBER_TOO_NEW) andInvalid. It threw aSupraAPIErrorwith status 400 forFailonly. WithenableTransactionSimulation: true, a failed simulation means the transaction is not submitted. That simulation handlesSEQUENCE_NUMBER_TOO_NEWas the max gas estimate does: behind numbers that have records of transactions this client submitted, the transaction is simulated with the account's sequence number on the chain and submitted with its own; otherwise a helper's transaction is signed again with the lowest number without a record, and a transaction with an explicit number throws the failure. A failed read of the account during that check is thrown, as in the estimate, and nothing is submitted. - Breaking:
waitForTransactionand submissions withenableWaitForTransactionkeep waiting while the status isPendingorPendingAfterExecutionand while a read fails (including HTTP 404 for a transaction the node has not seen yet), until the wait timeout measured in wall-clock time. A timeout throwsSupraTransactionTimeoutError, and aFailorInvalidoutcome throwsSupraTransactionFailedError; both threw aSupraAPIErrorwith status 500. The default timeout is 60 seconds; submissions used 20 seconds. - Breaking: the submit helpers listed above return
SubmitTransactionResponse(TransactionResponse | NotReadBackTransactionResponse). WithoutenableWaitForTransaction, when the node accepts the transaction and the read that follows fails, they return{ hash, status: "NotReadBack", readError }; they threw the read's error, which did not carry the hash. - Breaking:
isPendingTransactionreturns true forPendingAfterExecutionas well asPending. - Breaking:
deriveTransactionHashreturns the hash with a0xprefix, the formgetTransactionByHashandwaitForTransactionaccept. It returned 64 hex characters without the prefix. The submit helpers derive the hash of each transaction the same way before they submit it. - Breaking:
transaction.submit.submitMultiAgentTransactionandsubmitSponsorTransaction, and the matching methods of a built transaction, throw aRangeErrorbefore submitting when a secondary signer or fee payer address is not 1 to 64 hex digits after an optional0x. They sent the transaction, which the node refused. - Breaking:
transaction.submit.submitSerializedRawTransactionAndSignatureandsubmitTransactionAndSignatureof a built transaction throw aRangeErrornamingsenderPubkeyorsignaturebefore submitting when that value is not hex digits in pairs after its0xprefix. They sent the transaction, which the node refused. - Breaking:
getTransactionByHashtakes no type argument. It returnsTransactionResponse, which is narrowed bytxn_type; the type argument did not change the value returned. - Breaking:
AutomationRegistrationPayloadJSON.AutomationRegistrationisAutomationRegistrationParamV1JSON | AutomationRegistrationParamV2JSON(it wasAutomationRegistrationParamV1JSON), since a registration can carry version 2 parameters. Code that reads.V1of it no longer compiles until it narrows the union first, for example with"V1" in payload.AutomationRegistration. - Breaking:
DEFAULT_MAX_GAS_UNITSis 20,000 units (was 1,000). It is the max gas of a transaction that sets none when the estimate is turned off or the estimating simulation could not run to a result (a request error, a response withoutgas_used), and of the builders that cannot estimate. The node requires the sender's balance to pay formax gas × gas unit price: 20 SUPRA at a gas unit price of 100,000 quants. A sender with less must setmaxGason the builders that make no request. - Breaking: a transaction without a
gasUnitPriceon the call or the client carries the node's estimate,max(median_gas_price, min_configured_gas_price), read from the node for each transaction (in the helpers that submit the read starts when the call is made and is awaited in the call's turn for the sender's account, so calls from one account keep the order of the calls, except SUPRA fungible asset transfers, whose balance check is awaited before the lock is requested, and the multisig propose and execute helpers (proposeMultisigTransaction,proposeMultisigTransactionWithHash,executeMultisigTransaction), whose reads of the proposal's function ABI and of the next proposal are awaited before the lock is requested, and for these two the price read starts after those reads, not when the call is made;transaction.build.simpleawaits it before it builds); the same price is used for the max gas estimate. It wasSupraConfig.minGasUnitPrice, elseDEFAULT_GAS_PRICE(100,000 quants), without reading the node. A failed read of the estimate throws its error and nothing is submitted. A price of the call or the client is used as given. - Breaking:
SupraConfig.minGasUnitPriceandNetworkConfig.minGasUnitPriceare renamedgasUnitPrice, without an alias.SupraClient.networkInformation.gasUnitPriceisundefinedwhen the configuration sets none. - Breaking: the builders that make no request (
rawTxnObject,scriptRawTxnObject,automationRegistrationRawTxnObject,multisigRawTxnObject,multisigProposalTxRawTxnObject) throw aRangeErrorbefore building when neither the call nor the client sets agasUnitPrice; they cannot read the node's estimate. - Breaking: a submission or a simulation refused for a gas unit price below the node's minimum throws
SupraGasUnitPriceBelowMinimumError, which is neither aSupraAPIErrornor aSupraSimulationFailedError; the original error is itscause. - The JSDoc of
getGasPrice()andgetMinGasUnitPrice()no longer says that transactions do not use them. - Breaking: without a
maxGason the call or the client, a transaction's max gas is estimated by the methods listed under Added, andtransaction.build.simpleusesDEFAULT_MAX_GAS_UNITSat most what the sender's balance pays for (one balance read). These methods make a balance read and, excepttransaction.build.simple, a simulation request before the submission. A transaction whose estimating simulation has a status other thanSuccess(an abort,OUT_OF_GAS,PendingAfterExecution,Invalid) throwsSupraSimulationFailedErrorand is not submitted. - Breaking:
SupraClient.networkInformation.maxGasisundefinedwhenSupraConfig.maxGasis not set; it wasDEFAULT_MAX_GAS_UNITS. - Breaking:
coin.transferSupraCoin,coin.transferCoin,fungibleAsset.transferSupraFungibleAsset,fungibleAsset.transferFungibleAsset,transaction.publishPackageand the entry functions ofContract.fromABI(and the newfungibleAsset.migrateCoinToFungibleStore, the automation task helpers and the multisig helpers) take the sequence number from the client's counter instead of reading it from the chain on every call, and the calls of one client from one account are submitted one after another (see the counter under Added); they ran independently of each other. Transactions sent by other means from the same account (another client or process, a wallet) make the counter stale: a helper call whose number such a transaction holds is refused, sent once more after a read of the chain, and refused again while that transaction is pending; the next call after it has committed takes the next number. Transactions submitted through the client, including those built with an explicit number, are recorded and do not make it stale. A transaction that will not commit keeps its number until the timestamp of a latest block the client reads reaches its expiration time. A transaction the node discarded after accepting it frees its number when any read of it through the client (waitForTransaction,getTransactionByHash,isPendingTransaction, a submission's wait or read-back) returnsInvalid. - Breaking: a transaction built without
txExpiryTimeexpiresDEFAULT_TX_EXPIRATION_DURATION(now 60) seconds after the client's clock in whole seconds, orSupraConfig.txExpirySecsseconds (at most 5 seconds less than the node's maximum time to live, whichGET /rpc/v3/transactions/parametersserves); it expired 300 seconds after the client's clock. This applies to every builder, includingrawTxnObjectand the other builders oftransaction.build. The node refuses a transaction whose expiration time is not after its clock or more than its maximum after it, so a client whose clock is far from the node's has its transactions refused. A transaction whose expiration time is more than the node's maximum after the client's clock is refused with aRangeErrorbefore signing, where 1.2.0 sent it and the node refused it. SettxExpiryTime(absolute, used as given) ortxExpirySecsfor a transaction that is signed or submitted later. - Breaking:
signTransaction,transaction.build.signedTransaction,transaction.build.sendTxnPayloadand thesignTransaction,signedTransactionandsendTxnPayloadmethods of a built transaction return promises, since a client's first signature reads the node's chain ID. Code that already awaits them is unaffected. - Breaking: a client whose configured chain ID differs from its node's throws
SupraChainIdMismatchErrorfrom every signing path, including the submit helpers and transfers, unlessverifyChainId: falseis set. - Breaking:
getChainId()returns a promise that resolves to the node's chain ID; it returned the configured chain ID synchronously. WithverifyChainId: falseit resolves to the configured chain ID without a request. - Breaking:
validateChainId()throwsSupraChainIdMismatchError, whose message isThe configured chain ID <configured> does not match the node's chain ID <node>; it threw a plainError. It reads the node's chain ID once per client and shares it with signing andgetChainId(). - Breaking:
new SupraClientthrows aRangeErrorwhen thechainIdof a custom configuration is not an integer from 0 to 255, and aTypeErrorwhenverifyChainIdis not a boolean. - Breaking: integer arguments given as strings (
u8tou256in entry functions,u8tou256andi8toi256in views) must be decimal digits, with a leading-for signed types, or, for entry functions,0xfollowed by hex digits. Empty and whitespace-only strings, strings with surrounding whitespace,"1.5","-1"for unsigned types,"0x"and values above the maximum of the type throw before any request, with an error naming the argument index and type. Previously""and" "were encoded as 0 and padded strings were accepted. - Breaking: integer arguments of views given in any form (number, bigint or string) must lie in the range of the type,
0to2^n - 1forunand-2^(n-1)to2^(n-1) - 1forin; other values throw before any request. Views sent them to the node, which refused them (u8300,u64-1). - Breaking: a
numbergiven for an integer argument of an entry function or a view must be a safe integer (at mostNumber.MAX_SAFE_INTEGER, 2^53 - 1, in magnitude); larger values are given as abigintor a decimal string. A largernumbersuch as2 ** 53 + 1holds a rounded value, which was encoded. - Breaking:
methods.viewencodes anOption<u8>argument the way the node reads it, as the hex of the byte (Some(16)is{"vec":"10"}). It was sent as the decimal string, which the node read as a different byte or rejected.Option<T>for every otherTis a one-element array of the encoded value,Noneis an empty array, andOption<vector<u8>>carries the hex of the bytes. - A
vector<u8>argument of a view is validated: a string must be hex of whole bytes, with or without0x, and array elements must be integers from 0 to 255. - Breaking: a
boolargument of a view is a boolean or one of the strings"true"and"false"; other values throw before any request. Views converted the value withBoolean(value), which sent"false"and"0"astrue. Entry functions accept the same two strings, so both encode a value alike. - Breaking:
addressand0x1::object::Object<T>arguments of entry functions and views must be a string or aHexStringholding 1 to 64 hex digits after an optional0x. Other values, including""and"0x", throw before any request. Entry functions encoded""and"0x"as the address0x0, and views sent every value to the node, converted withString(value)foraddressand unchanged forObject<T>. - Breaking: type arguments given as strings are parsed by the SDK with the grammar of the node's type parser, in entry functions (
transaction.build.simpleand the entry functions ofContract.fromABI) andmethods.view. ThecoinTypeofcoin.transferCoinand offungibleAsset.migrateCoinToFungibleStoreis checked byvalidateStructIdand then parsed the same way. A string that is not exactly one concrete type throws before any request: text after the type ("u64 junk","0x1::supra_coin::SupraCoin, u8"), a generic type parameter ("T0"),"string", which was read as0x1::string::Stringand which nodes refuse, and a type with more than eight nestedvectorand struct levels, the most a transaction can carry. Entry functions used the first type of such a string, and views sent it to the node unchecked. - Breaking (types):
FunctionTypeArgs, the type of an entry inty_argsof a transaction payload in JSON form, is a union of the primitive type names,{ vector }and{ struct }instead of an interface that only describes{ struct }. Code that readsty_args[i].structdirectly must narrow the value first. - Breaking:
signTransactionhas one signature per kind of transaction: it resolves to theHexStringsignature for aRawTransactionand to theAccountAuthenticatorEd25519for aMultiAgentRawTransactionorFeePayerRawTransaction, and toHexString | AccountAuthenticatorEd25519for anAnyRawTransaction. Casts of the result are no longer needed.ExtendedRawTransaction.signTransactionresolves toHexString. - Breaking:
PaginatedResponse.cursorisundefinedexactly at the end of a feed, on v11 and v12 nodes alike. The empty header, the"0"ofcoin_transactionsand the echoedstartofresourcesandmodulesthat v11 nodes send at the end of a feed are returned asundefined. A page can be empty and still carry a cursor. The cursor"0"is the position of a row of block 0 (timestamp 0), so forgetAccountCoinTransactionsandgetAccountFaTransactionsan empty page with"0"for a request with nostart, ascending order and atypefilter returnscursor"0"instead ofundefined: the page scanned only a genesis row that the filter excluded. The request withstart"0"continues the feed, or on a feed without rows returns"0"again, which ends it. - Breaking:
getEventsByTypetypesoptions.startasstring, the type of the cursor it returns. It wasnumber. - Every cursor option (
startorcursor) acceptsundefined, so a returned cursor is passed back without a check or a cast. An empty cursor is not sent. - Breaking:
CommittedTransactionResponseandTransactionResponseincludeSettlementTransactionResponse. Code that readsheader,payloadorauthenticatormust narrow ontxn_typefirst. - Breaking:
EmptyTransactionOutputis the string"Empty", which is what the node sends. It was declared as{ Empty: null }. - Breaking:
PendingTransactionResponse.txn_typeisTransactionType.User.BlockMetadataTransactionResponseandAutomationRecordTransactionResponsedeclareoutputas non-null.block_headeris optional on every transaction response, as the node's API schema declares it; transactions returned as part of a block haveblock_header: null. - Breaking:
FinalizedBlockHeader.transactionsis optional, since the node omits it unless the block is requested withwithFinalizedTransactions: true, and is typedCommittedTransactionResponse[]. - Breaking:
AutomationRegistrationParamsV2, the version 2 registration in a transaction response, typestask_typeas"user" | "system"andtask_priorityasnumber | null, which is what v11.7.0 and v12 nodes send. They were declared"User" | "System"and an optionalnumber. - The
typeoption ofgetBlockByHeightandgetTransactionsByBlockHashisTransactionQueryType, which adds"record"and"settlement". - Breaking:
isAccountExistsreturnsfalseonly when the node reports the account as absent (HTTP 404 on v12 nodes, HTTP 400 with a "Resource not found" message on v11 nodes). Every other failure, such as an unreachable node, a timeout, HTTP 429 or HTTP 5xx, is thrown. - Breaking:
new SupraClientthrows aTypeErrorwhenrpcUrlis not an absolutehttp:orhttps:URL. rpcUrlmay end in slashes and may carry a path prefix (https://host/prefix/); every request goes to the same URL whichever form is configured.- Breaking:
SupraClient.configis a copy of the configuration object passed to the constructor, no longer that object. - Clients of a predefined network no longer share one mutable network configuration: the gas, timeout and retry settings of one
SupraClientno longer reach another client of the same network. SupraConfigdocuments which settings belong to a client: all of them.- Breaking: the
SupraClienttype no longer declaresbuild,simulateandsubmit, which wereundefinedat runtime. Usesupra.transaction.build,supra.transaction.simulateandsupra.transaction.submit. - Breaking:
fungibleAsset.transferSupraFungibleAsset, andfungibleAsset.transferFungibleAssetwith the SUPRA fungible asset address, read the sender's fungible asset balance first and throwSupraInsufficientFungibleAssetBalanceErrorwithout submitting a transaction when it is belowamount. The transfer moves only the fungible asset store; SUPRA that an account received as a coin (for example from the faucet) is in itsCoinStoreuntilfungibleAsset.migrateCoinToFungibleStoremoves it. Before, the transaction was submitted and aborted on chain.coin.transferSupraCoinmoves SUPRA held in either form. account.getAccountSupraCoinBalanceandaccount.getAccountCoinBalancewith a coin type return the total SUPRA balance (CoinStoreplus the paired fungible asset store);getAccountCoinBalancewith a fungible asset address returns that asset's primary store only, so it is 0 for SUPRA that has not been migrated. The behaviour is unchanged; the documentation now states it.- Breaking:
account.getAccountCoinsCountalso counts SUPRA held as a fungible asset when the account has noCoinStore<SupraCoin>, so a migrated account returns 1 where it returned 0. Fungible assets other than SUPRA are not counted: the node has no listing of an account's fungible asset stores. getFungibleAssetMetadatais declared to returnFungibleAssetMetadata(name,symbol,decimals,icon_uri,project_uri), which is what it returns. It was declaredCoinInfo.- The examples
buildTransaction.tsandsubmitTransaction.tsread a fresh sequence number for each transaction (they reused the number of the first one), use the client's RPC URL for the raw HTTP request, and take the automation gas price cap from the network's minimum gas unit price. - Breaking:
standardizeAddressreturns lower-case hex and accepts a0xor0Xprefix. It throws aRangeErrorfor a value that is not 1 to 64 hex digits after the optional prefix (for example"","0x","0xzz"or 65 digits); it threw aSupraAPIErrorwith status 400 that no node sent for more than 64 digits, and returned other malformed values with the prefix doubled or the invalid characters kept. An address in upper case now matches the SUPRA fungible asset address, andresetSequenceNumberfinds the counter of such an address. The methods that take an address without validating it first (fundAccountWithFaucet,getFaucetTransaction,resetSequenceNumberand the builders oftransaction.build) throw thisRangeErrorbefore any request. - Breaking:
getTransactionByHash,waitForTransactionandisPendingTransactionrequire a transaction hash of0xfollowed by exactly 64 hex digits. A longer or shorter value is rejected before any request. - Breaking:
getAccountModulerequiresmoduleNameto be a Move identifier, and the resource, event and coin type arguments of the account, event, coin and fungible asset methods require the module and struct names of the type to be Move identifiers (a letter or underscore, then letters, digits and underscores). Other values are rejected before any request. The resource and event type and the module name are percent-encoded in the request path.
Fixed
- A view argument of type
0x1::object::Object<…>inside avectoror anOption(for examplevector<Object<Metadata>>) is sent as{ inner: <address> }, the form the node reads there. It was sent as the address, which the node refused. A top-levelObject<…>argument is still sent as the address. transaction.build.multisigRawTxnObjectbuilds the execution of a proposal whose payload is stored on chain (create_transaction) whenfunction,functionTypeArgsandfunctionArgsare left out. The payload JSON of the submission carries notransaction_payloadthen; it threwMultisig payload is missing. The derived transaction hash is the node's for this kind of transaction.- A submission that the node accepts with a 2xx status whose body is not a transaction hash (a body that is not JSON, an empty body, or a value that is not a hash) is handled as an accepted submission with the hash derived from the signed transaction: the wait or the read-back uses that hash. A body that was not JSON threw a
SupraAPIErrorwith the 2xx status, and the other bodies were returned as the hash. - A submission through
transaction.submit.*or the submit methods of a built transaction that the node refuses with a 400 because its pool already holds the submitted transaction, for example when the same signed transaction is submitted twice, is no longer thrown asSupraAPIError. The transaction commits at most once. A v12 node names the transaction (transaction <hash> is already pending) after it has forwarded it again: the submission is handled as accepted with the hash derived from the signed transaction, and the wait or the read-back uses that hash. A v11.7 node answersAlready scheduled digest=<hash>, ..., also when its pool holds another transaction with the same sequence number at a gas unit price at least this one's, and does not forward the submission, so the transaction is read by hash once, within 5 seconds and without retries:SuccessorFailis handled as accepted;Pending, another non-final status, or a failed read other than a 404 throwsSupraSubmissionOutcomeUnknownErrorwith the refusal ascauseand the read's status asreadStatusor its error asreadError(or waits for the hash withenableWaitForTransaction); a 404 orInvalidthrows the refusal asSupraAPIError, as in 1.2.0. simulatesends a copy of the payload with zero signatures and does not modify the caller's payload; the caller's signatures were replaced with zeros when the simulation request failed.coin.transferSupraCoin,coin.transferCoin,fungibleAsset.transferSupraFungibleAssetandfungibleAsset.transferFungibleAssetsubmit themaxGas,gasUnitPriceandtxExpiryTimeofoptionalTransactionArgs.optionalTransactionPayloadArgs; they used the client's settings. A transfer of SUPRA withcoin.transferCointo a new account no longer runs out of gas with the default settings.- No method modifies the options object it is given: the transfers no longer write a
maxGasintooptionalTransactionPayloadArgs, andmethods.viewno longer writes the fetched ABI into the caller's arguments. transferSupraCoin,transferCoin,transferFungibleAssetandtransferSupraFungibleAssetencode the receiver and asset addresses as 32 bytes, left-padded with zeros, for every address thatvalidateAddressaccepts (1 to 64 hex characters). Addresses of 63 or fewer characters previously threw or were sent as arguments shorter than 32 bytes. The address of the sender of a raw transaction, the multisig address and the module address are padded the same way.- Entry function arguments of type
vector<u8>acceptnumber[],Uint8Array,ArrayBufferand hex strings with or without0x, with identical BCS. Previously onlynumber[]was accepted although the argument types admit the other forms. transaction.build.simpleremoves every leading&signerandsignerparameter of the entry function from the expected arguments, not only the first, so functions with several signer parameters can be built.- Type arguments of every
TypeTagvariant (bool,u8tou256,address,signer,vectorandstructwith type parameters, nested to any depth) are written correctly in transaction payloads. Building, simulating or submitting an entry function, script, automation registration or multisig transaction with a non-struct type argument previously threw aTypeError. methods.viewwrites aTypeTagtype argument as its full Move type string, including the type parameters of a struct, and accepts non-structTypeTagvalues. ATypeTagand its string form produce the same request.- A type argument string
0x1::object::Object<T>is the struct typeObject<T>in an entry function payload, alone and insidevector<…>or another struct; it was signed asaddress. A view function and an entry function given the same type argument string instantiate the same type. addressandObject<T>arguments of entry functions accept aHexString, as their declared typeAccountAddressInputstates; they threwExpected string for address, got object. AHexStringObject<T>argument of a view is sent as its address string; it was sent as the object{"hexString":…}.- Type argument strings whose module or struct names contain
Tfollowed by digits, such as0xabc::usdt0::USDT0or0xabc::m::T1, are accepted in entry functions and as thecoinTypeofcoin.transferCoinandfungibleAsset.migrateCoinToFungibleStore; they threwTypeTagParserError: Invalid type tag. - Script arguments of type
u16are accepted byparseScriptArgs; previously they threwInvalid script argument variant.u32andu256script arguments are covered by tests. getAccountInforeturnssequence_numberas abigint, the declared type. It returned the number the node sends, soinfo.sequence_number + 1nthrew aTypeError.supra.constructorisSupraClient; it was the constructor of the last mixed-in class.- The JSDoc of
events.getEventsByTypedescribes events and callsgetEventsByType. - Every example in the JSDoc of the public API compiles against the 2.0.0 API (imports from
supra-ts-sdk, awaited signing, current option names, self-contained accounts and addresses); several imported fromsupra-l1-sdkor called methods that do not exist. The descriptions ofgetCoinInfo, the transfers,publishPackage, thetransaction.submitmethods,fundAccountWithFaucet,methods.view,getGasPrice,getMinGasUnitPriceand theSupraClientconstructor state the behaviour of 2.0.0: units, the sequence-number counter, the chain ID check, the errors thrown, and where the gas unit price comes from. .claude/skills/supra-ts-sdk/SKILL.md, which the package ships, describes 2.0.0: gas estimation, per-call gas settings and the 20,000-unit default of the builders, the faucet on every network andSupraFaucetUnavailableError,isAccountExists, the typed errors, async signing, the chain ID check, the sequence-number counter,Network.DEVNET,migrateCoinToFungibleStore, cursors, and quants as the smallest SUPRA unit. Its code blocks type-check.- The
exportsmap ofpackage.jsongives therequirecondition its own declarations (dist/index.d.cts), so a CommonJS TypeScript project withmoduleResolutionnode16ornodenexttype-checksimport ... from "supra-ts-sdk"; the types resolved as an ES module before.
Removed
- Breaking:
DEFAULT_TXN_TIMEOUT_SEC;DEFAULT_TXN_WAIT_TIMEOUT_MSreplaces it. - Breaking:
DEFAULT_GAS_PRICE; the node's estimate is the default gas unit price. - Breaking:
DEFAULT_MAX_GAS_FOR_SUPRA_TRANSFER_WHEN_RECEIVER_EXISTSandDEFAULT_MAX_GAS_FOR_SUPRA_TRANSFER_WHEN_RECEIVER_NOT_EXISTS; the max gas estimate replaces the transfers' receiver-dependent max gas. - Breaking: the constants
DEFAULT_CHAIN_ID,MAX_RETRY_FOR_TRANSACTION_COMPLETION,DELAY_BETWEEN_POOLING_REQUESTandDEFAULT_RECORDS_ITEMS_COUNT. No function of the SDK read them; the chain ID comes fromSupraConfigand the wait is set bywaitTimeoutMs.
Security
supra-l1-sdk-coreis raised to^2.0.2.SupraAccount, which this package re-exports, no longer includes key material inJSON.stringifyoutput or in Node.jsutil.inspectandconsole.logoutput:JSON.stringifyreturns{ address, publicKeyHex }, andsigningKeyis a non-enumerable property.toPrivateKeyObject()exports the key.SupraAccount.fromDerivePaththrowsInvalid mnemonicfor a mnemonic that fails BIP-39 checksum or English wordlist validation.- Patched the dev-only transitive dependencies
handlebars(4.7.10; GHSA-xw65-4hp5-5hc7, GHSA-8r5x-fm3f-whwj, GHSA-p8wg-vrv2-v86f),brace-expansion(1.1.21, 2.1.7 and 5.0.12; GHSA-mh99-v99m-4gvg, GHSA-rgw5-rvv9-x895, GHSA-q2hr-2g5m-vwhr, GHSA-qhr7-859c-m2p7, GHSA-6j4f-fj2g-mc7p),browserslist(4.28.7; GHSA-c83g-rgw3-j3cx, GHSA-73wf-gq98-2v4g),baseline-browser-mapping(2.11.0; GHSA-w5vr-8v7q-w6rv),markdown-it(14.3.1; GHSA-253c-mchw-3w2r),@humanfs/node(0.16.8; GHSA-p498-v437-472g) andajv@6(6.14.0; GHSA-2g4f-4pwh-qvx6) throughpnpm.overrides. Each version is the minimum the override allows. They are reached only through the development toolchain (Jest, ts-jest, ESLint and TypeDoc), so no published artifact was affected.
Full Changelog: v1.2.0...v2.0.0