Skip to content

Commit a617f65

Browse files
committed
fix: Allow make builder functions to take in serialized post-conditions
1 parent b3fd80f commit a617f65

File tree

3 files changed

+84
-3
lines changed

3 files changed

+84
-3
lines changed

packages/transactions/src/builders.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import {
4545
createLPList,
4646
createSmartContractPayload,
4747
createTokenTransferPayload,
48+
deserializePostConditionWire,
4849
} from './wire';
4950

5051
/** @deprecated Not used internally */
@@ -248,7 +249,7 @@ export type BaseContractDeployOptions = {
248249
* transfered assets */
249250
postConditionMode?: PostConditionModeName | PostConditionMode;
250251
/** a list of post conditions to add to the transaction */
251-
postConditions?: PostCondition[] | PostConditionWire[];
252+
postConditions?: (PostCondition | PostConditionWire | string)[];
252253
/** set to true if another account is sponsoring the transaction (covering the transaction fee) */
253254
sponsored?: boolean;
254255
} & NetworkClientParam;
@@ -371,6 +372,7 @@ export async function makeUnsignedContractDeploy(
371372
: createStandardAuth(spendingCondition);
372373

373374
const postConditions: PostConditionWire[] = (options.postConditions ?? []).map(pc => {
375+
if (typeof pc === 'string') return deserializePostConditionWire(pc);
374376
if (typeof pc.type === 'string') return postConditionToWire(pc);
375377
return pc;
376378
});
@@ -417,7 +419,7 @@ export type ContractCallOptions = {
417419
* transfered assets */
418420
postConditionMode?: PostConditionModeName | PostConditionMode;
419421
/** a list of post conditions to add to the transaction */
420-
postConditions?: PostCondition[];
422+
postConditions?: (PostCondition | PostConditionWire | string)[];
421423
/** set to true to validate that the supplied function args match those specified in
422424
* the published contract */
423425
validateWithAbi?: boolean | ClarityAbi;
@@ -521,6 +523,7 @@ export async function makeUnsignedContractCall(
521523
: createStandardAuth(spendingCondition);
522524

523525
const postConditions: PostConditionWire[] = (options.postConditions ?? []).map(pc => {
526+
if (typeof pc === 'string') return deserializePostConditionWire(pc);
524527
if (typeof pc.type === 'string') return postConditionToWire(pc);
525528
return pc;
526529
});

packages/transactions/tests/builder.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2972,4 +2972,3 @@ describe('multi-sig', () => {
29722972
await expect(txMismatch).rejects.toThrow();
29732973
});
29742974
});
2975-

packages/transactions/tests/postcondition.test.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ import {
2525
} from '../src/postcondition';
2626
import { StacksWireType, parseAssetString, parsePrincipalString } from '../src/wire';
2727
import { serializeDeserialize } from './macros';
28+
import {
29+
StxPostCondition,
30+
FungiblePostCondition,
31+
NonFungiblePostCondition,
32+
} from '../src/postcondition-types';
2833

2934
test('STX post condition serialization and deserialization', () => {
3035
const postConditionType = PostConditionType.STX;
@@ -366,3 +371,77 @@ describe('conditionBytesToType', () => {
366371
}
367372
);
368373
});
374+
375+
describe('Pc.fromHex', () => {
376+
test('deserializes STX post condition from hex', () => {
377+
const postConditionHex = '00021a5dd8ff3545259925b982524807686567eec2933f03000000000000000a';
378+
const postCondition = Pc.fromHex(postConditionHex) as StxPostCondition;
379+
380+
expect(postCondition.type).toBe('stx-postcondition');
381+
expect(postCondition.address).toBe('ST1EXHZSN8MJSJ9DSG994G1V8CNKYXGMK7Z4SA6DH');
382+
expect(postCondition.condition).toBe('gte');
383+
expect(postCondition.amount).toBe('10');
384+
});
385+
386+
test('deserializes FT post condition from hex', () => {
387+
const postConditionHex =
388+
'01021a5dd8ff3545259925b982524807686567eec2933f1ac989ba53bbb27a76ef5e8499e65f69c7798fd5d113746573742d61737365742d636f6e74726163740f746573742d61737365742d6e616d650400000000000003e8';
389+
const postCondition = Pc.fromHex(postConditionHex) as FungiblePostCondition;
390+
391+
expect(postCondition.type).toBe('ft-postcondition');
392+
expect(postCondition.address).toBe('ST1EXHZSN8MJSJ9DSG994G1V8CNKYXGMK7Z4SA6DH');
393+
expect(postCondition.condition).toBe('lt');
394+
expect(postCondition.amount).toBe('1000');
395+
expect(postCondition.asset).toBe(
396+
'ST34RKEJKQES7MXQFBT29KSJZD73QK3YNT5N56C6X.test-asset-contract::test-asset-name'
397+
);
398+
});
399+
400+
test('deserializes NFT post condition from hex', () => {
401+
// NFT post condition where asset ID is a buffer of string "token-asset-name"
402+
const postConditionHex =
403+
'02021a5dd8ff3545259925b982524807686567eec2933f1ac989ba53bbb27a76ef5e8499e65f69c7798fd5d113746573742d61737365742d636f6e74726163740f746573742d61737365742d6e616d650200000010746f6b656e2d61737365742d6e616d6511';
404+
const postCondition = Pc.fromHex(postConditionHex) as NonFungiblePostCondition;
405+
406+
expect(postCondition.type).toBe('nft-postcondition');
407+
expect(postCondition.address).toBe('ST1EXHZSN8MJSJ9DSG994G1V8CNKYXGMK7Z4SA6DH');
408+
expect(postCondition.condition).toBe('not-sent');
409+
expect(postCondition.asset).toBe(
410+
'ST34RKEJKQES7MXQFBT29KSJZD73QK3YNT5N56C6X.test-asset-contract::test-asset-name'
411+
);
412+
413+
// Check that assetId is a BufferCV of "token-asset-name"
414+
expect(postCondition.assetId.type).toBe('buffer');
415+
expect(bytesToUtf8(hexToBytes((postCondition.assetId as BufferCV).value))).toBe(
416+
'token-asset-name'
417+
);
418+
});
419+
420+
test('deserializes origin principal post condition from hex', () => {
421+
// Origin STX post condition
422+
const postConditionHex = '0001030000000000000001';
423+
const postCondition = Pc.fromHex(postConditionHex) as StxPostCondition;
424+
425+
expect(postCondition.type).toBe('stx-postcondition');
426+
expect(postCondition.address).toBe('origin');
427+
expect(postCondition.condition).toBe('gte');
428+
expect(postCondition.amount).toBe('1');
429+
});
430+
431+
test('deserializes contract principal post condition from hex', () => {
432+
// Contract principal STX post condition
433+
const postConditionHex =
434+
'00031a5dd8ff3545259925b982524807686567eec2933f086b762d73746f72650300000000000186a0';
435+
const postCondition = Pc.fromHex(postConditionHex) as StxPostCondition;
436+
437+
expect(postCondition.type).toBe('stx-postcondition');
438+
expect(postCondition.address).toBe('ST1EXHZSN8MJSJ9DSG994G1V8CNKYXGMK7Z4SA6DH.kv-store');
439+
expect(postCondition.condition).toBe('gte');
440+
expect(postCondition.amount).toBe('100000');
441+
});
442+
443+
test('rejects invalid hex with descriptive error', () => {
444+
const invalidHex = 'not-a-valid-hex-string';
445+
expect(() => Pc.fromHex(invalidHex)).toThrow();
446+
});
447+
});

0 commit comments

Comments
 (0)