Skip to content
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
29 changes: 29 additions & 0 deletions modules/sdk-coin-stx/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ import {
deserializeTransaction,
PubKeyEncoding,
publicKeyFromSignature,
serializeCV,
signWithKey,
StacksTransaction,
standardPrincipalCV,
TransactionVersion,
validateStacksAddress,
} from '@stacks/transactions';
Expand Down Expand Up @@ -505,6 +507,33 @@ export function getAddressVersion(address: string): AddressVersion {
return createAddress(baseAddress).version;
}

/**
* Encode a Stacks *standard* principal as the Clarity SIP-005 hex wire format
* — a 22-byte blob:
*
* `0x05` || version (1 byte) || hash160 (20 bytes)
*
* Contract principals (`<address>.<contract-name>`) and addresses with a
* `?memoId=…` suffix are rejected. The Clarity type byte (`0x05`) is set
* by `serializeCV` from `@stacks/transactions`, so this helper does not
* hand-roll any byte concatenation.
*
* @param {string} principal a Stacks standard principal (e.g. `SP…` / `ST…`)
* @returns {string} hex-encoded 22-byte Clarity standard principal
*/
export function getEncodedPrincipal(principal: string): string {
if (principal.includes('?')) {
throw new UtilsError(`principal must not include a query string: ${principal}`);
}
if (principal.includes('.')) {
throw new UtilsError(`contract principals are not supported, expected a standard principal: ${principal}`);
}
if (!isValidAddress(principal)) {
throw new UtilsError(`invalid Stacks address in principal: ${principal}`);
}
return serializeCV(standardPrincipalCV(principal)).toString('hex');
}

/**
* Returns a STX pub key from an xpub
*
Expand Down
26 changes: 26 additions & 0 deletions modules/sdk-coin-stx/test/unit/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,32 @@ describe('Stx util library', function () {
});
});

describe('getEncodedPrincipal', function () {
it('should encode a testnet standard principal as the 22-byte Clarity blob', function () {
Utils.getEncodedPrincipal('ST390D0WBF60T25P36KMCP6WN1BXQ7TTMMQKNV15C').should.equal(
'051ad206838b7981a116c334e8cb1b950afb73eb54a5'
);
});

it('should reject contract principals', function () {
should.throws(
() => Utils.getEncodedPrincipal('ST390D0WBF60T25P36KMCP6WN1BXQ7TTMMQKNV15C.my-contract'),
/contract principals are not supported/
);
});

it('should reject addresses with a memoId suffix', function () {
should.throws(
() => Utils.getEncodedPrincipal('ST390D0WBF60T25P36KMCP6WN1BXQ7TTMMQKNV15C?memoId=0'),
/must not include a query string/
);
});

it('should reject invalid addresses', function () {
should.throws(() => Utils.getEncodedPrincipal('not-a-stacks-address'), /invalid Stacks address/);
});
});

describe('xpubToSTXPubkey', function () {
it('should succeed to convert for valid xpubs', function () {
Utils.xpubToSTXPubkey(
Expand Down
Loading