Publish a Package
How to publish a package using the TypeScript SDK.
publishPackage function
The function lives on the client’s transaction module and takes a single named-argument object.
await supra.transaction.publishPackage({ senderAccount, packageMetadata, modulesCode })Parameters
| Name | Type |
|---|---|
| senderAccount | SupraAccount |
| packageMetadata | Uint8Array |
| modulesCode | Uint8Array[] |
| optionalTransactionArgs? | OptionalTransactionArgs |
Returns
| Name | Type |
|---|---|
| Promise<TransactionResponse> | TransactionResponse |
The function returns the transaction, not a { txHash, result } pair. With enableWaitForTransaction: true in
enableTransactionWaitAndSimulationArgs, it waits for a final status and returns the committed transaction. A
transaction that ends with Fail or Invalid throws SupraTransactionFailedError, and one with no final status within
the wait timeout throws SupraTransactionTimeoutError. Without enableWaitForTransaction, it returns the transaction
as the node reports it right after the submission, with its hash.
Max gas
When neither the call nor the client sets maxGas, publishPackage estimates it: it simulates the transaction with the
largest max gas the sender’s SUPRA balance pays for and submits it with 1.5 times the gas used. A simulation that does
not succeed throws SupraSimulationFailedError and nothing is submitted. The sender needs enough SUPRA to cover the
estimate at the gas unit price (see Gas price). To set the limit yourself,
pass maxGas in optionalTransactionPayloadArgs.
Example
The publishPackage function requires the package metadata and module bytecode as the packageMetadata and modulesCode arguments. These are obtained through the build-publish-payload command of the Supra CLI. Once obtained, parse the JSON file for the data and pass it to the publishPackage function.
Prepare an account and a package
The example publishes a package named counter from a funded account. Create the account as in
Create Supra Accounts, keep its private key, and fund its
address from the faucet on Devnet. The example uses Devnet; use Network.TESTNET and a Testnet
account for Testnet.
Create the counter package as in Create a Move Package, which
also covers its Move.toml and the framework dependency. In Move.toml, give the named address counter_addr the
address of the account:
[addresses]
counter_addr = "<ACCOUNT_ADDRESS>"Save this module as sources/counter.move:
module counter_addr::counter {
use std::signer;
use supra_framework::event;
struct Counter has key {
value: u64,
}
#[event]
struct Bumped has drop, store {
account: address,
value: u64,
}
/// Adds one to the signer's counter, creating the counter on the first call.
public entry fun bump(account: &signer) acquires Counter {
let addr = signer::address_of(account);
if (!exists<Counter>(addr)) {
move_to(account, Counter { value: 0 });
};
let counter = borrow_global_mut<Counter>(addr);
counter.value = counter.value + 1;
event::emit(Bumped { account: addr, value: counter.value });
}
#[view]
public fun get(addr: address): u64 acquires Counter {
if (exists<Counter>(addr)) borrow_global<Counter>(addr).value else 0
}
}Build the publish payload with the Supra CLI
supra move tool build-publish-payload --package-dir /supra/move_workspace/{YOUR_PROJECT_NAME} --json-output-file /supra/move_workspace/{YOUR_PROJECT_NAME}/publish-payload.jsonThe command compiles the package, so every named address in Move.toml needs a value, either under [addresses] or
with --named-addresses. Without one, compilation fails with address '<NAME>' is not assigned a value.
supra move tool build-publish-payload --package-dir /supra/move_workspace/{YOUR_PROJECT_NAME} --json-output-file /supra/move_workspace/{YOUR_PROJECT_NAME}/publish-payload.json --named-addresses {NAME}={ACCOUNT_ADDRESS}Initialize a new project
mkdir supra-publish && cd supra-publish
npm init -y
npm install supra-ts-sdk@devnet
npm install --save-dev tsxtsx runs TypeScript files directly. The TypeScript SDK page lists
the npm dist-tags.
Create publish_example.ts and import dependencies
publish_example.ts
import fs from 'fs';
import { HexString, SupraAccount, SupraClient, Network } from 'supra-ts-sdk';Parse the JSON file and extract data
publish_example.ts
function getPackageData(filePath: string) {
const jsonData = JSON.parse(fs.readFileSync(filePath, "utf8"));
const packageMetadata = new HexString(jsonData.args[0].value).toUint8Array();
const modulesCode = [];
for(let e of jsonData.args[1].value){
modulesCode.push(new HexString(e).toUint8Array())
}
return { packageMetadata, modulesCode };
}Call the publishPackage function
publish_example.ts
async function main(){
// The path to publish-payload.json, from the command line.
const { packageMetadata, modulesCode } = getPackageData(process.argv[2]);
const supra = new SupraClient({ network: Network.DEVNET });
// The private key of the funded account, from the environment.
const senderAccount = new SupraAccount(
new HexString(process.env.PRIVATE_KEY!).toUint8Array()
);
const publishTxn = await supra.transaction.publishPackage({
senderAccount,
packageMetadata,
modulesCode,
optionalTransactionArgs: {
enableTransactionWaitAndSimulationArgs: { enableWaitForTransaction: true },
},
})
// `Success` when the package is published. A transaction that fails throws
// SupraTransactionFailedError.
console.log(publishTxn.status, publishTxn.hash);
}Complete code
publish_example.ts
import fs from "fs";
import { HexString, SupraAccount, SupraClient, Network } from "supra-ts-sdk";
function getPackageData(filePath: string) {
const jsonData = JSON.parse(fs.readFileSync(filePath, "utf8"));
const packageMetadata = new HexString(jsonData.args[0].value).toUint8Array();
const modulesCode = [];
for(let e of jsonData.args[1].value){
modulesCode.push(new HexString(e).toUint8Array())
}
return { packageMetadata, modulesCode };
}
async function main(){
const { packageMetadata, modulesCode } = getPackageData(process.argv[2]);
const supra = new SupraClient({ network: Network.DEVNET });
const senderAccount = new SupraAccount(
new HexString(process.env.PRIVATE_KEY!).toUint8Array()
);
const publishTxn = await supra.transaction.publishPackage({
senderAccount,
packageMetadata,
modulesCode,
optionalTransactionArgs: {
enableTransactionWaitAndSimulationArgs: { enableWaitForTransaction: true },
},
})
console.log(publishTxn.status, publishTxn.hash);
}
main()Execute code
PRIVATE_KEY=<PRIVATE_KEY> npx tsx publish_example.ts <PATH_TO_PUBLISH_PAYLOAD_JSON>The module is then at <ACCOUNT_ADDRESS>::counter. Call a Function and Read
Events calls it.