Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor update stackstransaction constructor to options object #1751

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions .github/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,25 +229,33 @@ Namely, the node/API it is sent to will "broadcast" the transaction to the mempo

### `serialize` methods

Most users shouldn't need to use `serializeXyz` methods.
Concepts in Stacks.js have helpers like `postConditionToHex` instead.
Serialization is meant for internal representations in transactions, mostly not for user-facing data.

Existing methods now take or return **hex-encoded strings** _instead_ of `Uint8Array`s.

> If you were already converting returned bytes to hex-strings in your code, you can now skip the conversion step — hex-strings are the new default.

For easier migrating, renaming the following methods is possible to keep the previous behavior:

- `StacksTransaction.serialize` → `StacksTransaction.serializeBytes`
- `serializeCV` → `serializeCVBytes`
- `serializeAddress` → `serializeAddressBytes`
- `serializeAuthorization` → `serializeAuthorizationBytes`
- `serializeCV` → `serializeCVBytes`
- `serializeLPList` → `serializeLPListBytes`
- `serializeLPString` → `serializeLPStringBytes`
- `serializePayload` → `serializePayloadBytes`
- `serializePublicKey` → `serializePublicKeyBytes`
- `serializeStacksMessage` → `serializeStacksMessageBytes`
- `serializeMemoString` → `serializeMemoStringBytes`
- `serializeTransactionAuthField` → `serializeTransactionAuthFieldBytes`
- `serializeMessageSignature` → `serializeMessageSignatureBytes`
- `serializeMultiSigSpendingCondition` → `serializeMultiSigSpendingConditionBytes`
- `serializePayload` → `serializePayloadBytes`
- `serializePostCondition` → `serializePostConditionBytes`
- `serializePublicKey` → `serializePublicKeyBytes`
- `serializeSingleSigSpendingCondition` → `serializeSingleSigSpendingConditionBytes`
- `serializeSpendingCondition` → `serializeSpendingConditionBytes`
- `serializeStacksMessage` → `serializeStacksMessageBytes`
- `serializeStacksMessage` → `serializeStacksWireBytes`
- `serializeTransactionAuthField` → `serializeTransactionAuthFieldBytes`

### Asset Helper Methods

Expand Down
4 changes: 2 additions & 2 deletions packages/api/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
ClarityAbi,
ContractIdString,
FeeEstimation,
StacksTransaction,
StacksTransactionWire,
TxBroadcastResult,
broadcastTransaction,
fetchAbi,
Expand Down Expand Up @@ -65,7 +65,7 @@ export class StacksNodeApi {
* @returns a Promise that resolves to a {@link TxBroadcastResult} object
*/
broadcastTransaction = async (
transaction: StacksTransaction,
transaction: StacksTransactionWire,
attachment?: Uint8Array | string,
network?: StacksNetworkName | StacksNetwork
): Promise<TxBroadcastResult> => {
Expand Down
46 changes: 24 additions & 22 deletions packages/bns/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
NonFungiblePostCondition,
PostCondition,
ResponseErrorCV,
StacksTransaction,
StacksTransactionWire,
StxPostCondition,
UnsignedContractCallOptions,
bufferCV,
Expand Down Expand Up @@ -60,7 +60,9 @@ export interface BnsContractCallOptions {
postConditions?: PostCondition[];
}

async function makeBnsContractCall(options: BnsContractCallOptions): Promise<StacksTransaction> {
async function makeBnsContractCall(
options: BnsContractCallOptions
): Promise<StacksTransactionWire> {
const txOptions: UnsignedContractCallOptions = {
contractAddress: options.network.bootAddress,
contractName: BNS_CONTRACT_NAME,
Expand Down Expand Up @@ -271,15 +273,15 @@ export interface PreorderNamespaceOptions {
*
* @param {PreorderNamespaceOptions} options - an options object for the preorder
*
* @return {Promise<StacksTransaction>}
* @return {Promise<StacksTransactionWire>}
*/
export async function buildPreorderNamespaceTx({
namespace,
salt,
stxToBurn,
publicKey,
network,
}: PreorderNamespaceOptions): Promise<StacksTransaction> {
}: PreorderNamespaceOptions): Promise<StacksTransactionWire> {
const bnsFunctionName = 'namespace-preorder';
const saltedNamespaceBytes = utf8ToBytes(`${namespace}${salt}`);
const hashedSaltedNamespace = hash160(saltedNamespaceBytes);
Expand Down Expand Up @@ -328,7 +330,7 @@ export interface RevealNamespaceOptions {
*
* @param {RevealNamespaceOptions} options - an options object for the reveal
*
* @return {Promise<StacksTransaction>}
* @return {Promise<StacksTransactionWire>}
*/
export async function buildRevealNamespaceTx({
namespace,
Expand All @@ -338,7 +340,7 @@ export async function buildRevealNamespaceTx({
namespaceImportAddress,
publicKey,
network,
}: RevealNamespaceOptions): Promise<StacksTransaction> {
}: RevealNamespaceOptions): Promise<StacksTransactionWire> {
const bnsFunctionName = 'namespace-reveal';

return makeBnsContractCall({
Expand Down Expand Up @@ -401,7 +403,7 @@ export interface ImportNameOptions {
*
* @param {ImportNameOptions} options - an options object for the name import
*
* @return {Promise<StacksTransaction>}
* @return {Promise<StacksTransactionWire>}
*/
export async function buildImportNameTx({
namespace,
Expand All @@ -410,7 +412,7 @@ export async function buildImportNameTx({
zonefile,
publicKey,
network,
}: ImportNameOptions): Promise<StacksTransaction> {
}: ImportNameOptions): Promise<StacksTransactionWire> {
const bnsFunctionName = 'name-import';
const zonefileHash = getZonefileHash(zonefile);

Expand Down Expand Up @@ -449,13 +451,13 @@ export interface ReadyNamespaceOptions {
*
* @param {ReadyNamespaceOptions} options - an options object for the namespace ready transaction
*
* @return {Promise<StacksTransaction>}
* @return {Promise<StacksTransactionWire>}
*/
export async function buildReadyNamespaceTx({
namespace,
publicKey,
network,
}: ReadyNamespaceOptions): Promise<StacksTransaction> {
}: ReadyNamespaceOptions): Promise<StacksTransactionWire> {
const bnsFunctionName = 'namespace-ready';

return makeBnsContractCall({
Expand Down Expand Up @@ -491,15 +493,15 @@ export interface PreorderNameOptions {
*
* @param {PreorderNameOptions} options - an options object for the preorder
*
* @return {Promise<StacksTransaction>}
* @return {Promise<StacksTransactionWire>}
*/
export async function buildPreorderNameTx({
fullyQualifiedName,
salt,
stxToBurn,
publicKey,
network,
}: PreorderNameOptions): Promise<StacksTransaction> {
}: PreorderNameOptions): Promise<StacksTransactionWire> {
const bnsFunctionName = 'name-preorder';
const { subdomain } = decodeFQN(fullyQualifiedName);
if (subdomain) {
Expand Down Expand Up @@ -550,15 +552,15 @@ export interface RegisterNameOptions {
*
* @param {RegisterNameOptions} options - an options object for the registration
*
* @return {Promise<StacksTransaction>}
* @return {Promise<StacksTransactionWire>}
*/
export async function buildRegisterNameTx({
fullyQualifiedName,
salt,
zonefile,
publicKey,
network,
}: RegisterNameOptions): Promise<StacksTransaction> {
}: RegisterNameOptions): Promise<StacksTransactionWire> {
const bnsFunctionName = 'name-register';
const { subdomain, namespace, name } = decodeFQN(fullyQualifiedName);
if (subdomain) {
Expand Down Expand Up @@ -604,14 +606,14 @@ export interface UpdateNameOptions {
*
* @param {UpdateNameOptions} options - an options object for the update
*
* @return {Promise<StacksTransaction>}
* @return {Promise<StacksTransactionWire>}
*/
export async function buildUpdateNameTx({
fullyQualifiedName,
zonefile,
publicKey,
network,
}: UpdateNameOptions): Promise<StacksTransaction> {
}: UpdateNameOptions): Promise<StacksTransactionWire> {
const bnsFunctionName = 'name-update';
const { subdomain, namespace, name } = decodeFQN(fullyQualifiedName);
if (subdomain) {
Expand Down Expand Up @@ -657,15 +659,15 @@ export interface TransferNameOptions {
*
* @param {TransferNameOptions} options - an options object for the transfer
*
* @return {Promise<StacksTransaction>}
* @return {Promise<StacksTransactionWire>}
*/
export async function buildTransferNameTx({
fullyQualifiedName,
newOwnerAddress,
zonefile,
publicKey,
network,
}: TransferNameOptions): Promise<StacksTransaction> {
}: TransferNameOptions): Promise<StacksTransactionWire> {
const bnsFunctionName = 'name-transfer';
const { subdomain, namespace, name } = decodeFQN(fullyQualifiedName);
if (subdomain) {
Expand Down Expand Up @@ -730,13 +732,13 @@ export interface RevokeNameOptions {
*
* @param {RevokeNameOptions} options - an options object for the revoke
*
* @return {Promise<StacksTransaction>}
* @return {Promise<StacksTransactionWire>}
*/
export async function buildRevokeNameTx({
fullyQualifiedName,
publicKey,
network,
}: RevokeNameOptions): Promise<StacksTransaction> {
}: RevokeNameOptions): Promise<StacksTransactionWire> {
const bnsFunctionName = 'name-revoke';
const { subdomain, namespace, name } = decodeFQN(fullyQualifiedName);
if (subdomain) {
Expand Down Expand Up @@ -777,7 +779,7 @@ export interface RenewNameOptions {
*
* @param {RenewNameOptions} options - an options object for the renew
*
* @return {Promise<StacksTransaction>}
* @return {Promise<StacksTransactionWire>}
*/
export async function buildRenewNameTx({
fullyQualifiedName,
Expand All @@ -786,7 +788,7 @@ export async function buildRenewNameTx({
zonefile,
publicKey,
network,
}: RenewNameOptions): Promise<StacksTransaction> {
}: RenewNameOptions): Promise<StacksTransactionWire> {
const bnsFunctionName = 'name-renewal';
const { subdomain, namespace, name } = decodeFQN(fullyQualifiedName);
if (subdomain) {
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
SignedContractDeployOptions,
SignedTokenTransferOptions,
signWithKey,
StacksTransaction,
StacksTransactionWire,
TransactionSigner,
TxBroadcastResult,
validateContractCall,
Expand Down Expand Up @@ -704,7 +704,7 @@ async function sendTokens(_network: CLINetworkAdapter, args: string[]): Promise<
network,
};

const tx: StacksTransaction = await makeSTXTokenTransfer(options);
const tx: StacksTransactionWire = await makeSTXTokenTransfer(options);

if (estimateOnly) {
return fetchFeeEstimateTransfer({ transaction: tx, network }).then(cost => {
Expand Down Expand Up @@ -758,7 +758,7 @@ async function contractDeploy(_network: CLINetworkAdapter, args: string[]): Prom
fee,
nonce,
network,
postConditionMode: PostConditionMode.Allow,
postConditionMode: 'allow',
};

const tx = await makeContractDeploy(options);
Expand Down
12 changes: 9 additions & 3 deletions packages/stacking/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
OptionalCV,
PrincipalCV,
ResponseErrorCV,
StacksTransaction,
StacksTransactionWire,
TupleCV,
TxBroadcastResult,
UIntCV,
Expand Down Expand Up @@ -1569,9 +1569,15 @@ export class StackingClient {
/**
* Adjust microstacks amount for locking after taking into account transaction fees
*
* @returns {StacksTransaction} that resolves to a transaction object if the operation succeeds
* @returns {StacksTransactionWire} that resolves to a transaction object if the operation succeeds
*/
modifyLockTxFee({ tx, amountMicroStx }: { tx: StacksTransaction; amountMicroStx: IntegerType }) {
modifyLockTxFee({
tx,
amountMicroStx,
}: {
tx: StacksTransactionWire;
amountMicroStx: IntegerType;
}) {
const fee = getFee(tx.auth);
(tx.payload as ContractCallPayload).functionArgs[0] = uintCV(intToBigInt(amountMicroStx) - fee);
return tx;
Expand Down
40 changes: 31 additions & 9 deletions packages/transactions/src/authorization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,13 @@ function clearCondition(condition: SpendingConditionOpts): SpendingCondition {

export function serializeSingleSigSpendingCondition(
condition: SingleSigSpendingConditionOpts
): string {
return bytesToHex(serializeSingleSigSpendingConditionBytes(condition));
}

/** @internal */
export function serializeSingleSigSpendingConditionBytes(
condition: SingleSigSpendingConditionOpts
): Uint8Array {
const bytesArray = [
condition.hashMode,
Expand All @@ -224,6 +231,13 @@ export function serializeSingleSigSpendingCondition(

export function serializeMultiSigSpendingCondition(
condition: MultiSigSpendingConditionOpts
): string {
return bytesToHex(serializeMultiSigSpendingConditionBytes(condition));
}

/** @internal */
export function serializeMultiSigSpendingConditionBytes(
condition: MultiSigSpendingConditionOpts
): Uint8Array {
const bytesArray = [
condition.hashMode,
Expand Down Expand Up @@ -320,11 +334,14 @@ export function deserializeMultiSigSpendingCondition(
};
}

export function serializeSpendingCondition(condition: SpendingConditionOpts): Uint8Array {
if (isSingleSig(condition)) {
return serializeSingleSigSpendingCondition(condition);
}
return serializeMultiSigSpendingCondition(condition);
export function serializeSpendingCondition(condition: SpendingConditionOpts): string {
return bytesToHex(serializeSpendingConditionBytes(condition));
}

/** @internal */
export function serializeSpendingConditionBytes(condition: SpendingConditionOpts): Uint8Array {
if (isSingleSig(condition)) return serializeSingleSigSpendingConditionBytes(condition);
return serializeMultiSigSpendingConditionBytes(condition);
}

export function deserializeSpendingCondition(bytesReader: BytesReader): SpendingCondition {
Expand Down Expand Up @@ -674,17 +691,22 @@ export function setSponsor(
};
}

export function serializeAuthorization(auth: Authorization): Uint8Array {
export function serializeAuthorization(auth: Authorization): string {
return bytesToHex(serializeAuthorizationBytes(auth));
}

/** @internal */
export function serializeAuthorizationBytes(auth: Authorization): Uint8Array {
const bytesArray = [];
bytesArray.push(auth.authType);

switch (auth.authType) {
case AuthType.Standard:
bytesArray.push(serializeSpendingCondition(auth.spendingCondition));
bytesArray.push(serializeSpendingConditionBytes(auth.spendingCondition));
break;
case AuthType.Sponsored:
bytesArray.push(serializeSpendingCondition(auth.spendingCondition));
bytesArray.push(serializeSpendingCondition(auth.sponsorSpendingCondition));
bytesArray.push(serializeSpendingConditionBytes(auth.spendingCondition));
bytesArray.push(serializeSpendingConditionBytes(auth.sponsorSpendingCondition));
break;
}

Expand Down
Loading
Loading