Skip to content

Commit

Permalink
feat: support parsing btc address from a Clarity tuple value
Browse files Browse the repository at this point in the history
  • Loading branch information
zone117x committed May 17, 2021
1 parent b6ae9ef commit cb06f12
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 6 deletions.
50 changes: 44 additions & 6 deletions packages/stacking/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
// @ts-ignore
import { Buffer } from '@stacks/common';
import { AddressHashMode } from '@stacks/transactions';
import {
AddressHashMode,
BufferCV,
ClarityType,
ClarityValue,
TupleCV,
} from '@stacks/transactions';
import { address } from 'bitcoinjs-lib';
import BN from 'bn.js';
import { StackingErrors } from './constants';
Expand Down Expand Up @@ -85,11 +91,43 @@ export function decodeBtcAddress(btcAddress: string) {
};
}

export function poxAddressToBtcAddress(
version: Buffer,
hashBytes: Buffer,
network: 'mainnet' | 'testnet'
) {
export function extractPoxAddressFromClarityValue(poxAddrClarityValue: ClarityValue) {
const clarityValue = poxAddrClarityValue as TupleCV;
if (clarityValue.type !== ClarityType.Tuple || !clarityValue.data) {
throw new Error('Invalid argument, expected ClarityValue to be a TupleCV');
}
if (!('version' in clarityValue.data) || !('hashbytes' in clarityValue.data)) {
throw new Error(
'Invalid argument, expected Clarity tuple value to contain `version` and `hashbytes` keys'
);
}
const versionCV = clarityValue.data['version'] as BufferCV;
const hashBytesCV = clarityValue.data['hashbytes'] as BufferCV;
if (versionCV.type !== ClarityType.Buffer || hashBytesCV.type !== ClarityType.Buffer) {
throw new Error(
'Invalid argument, expected Clarity tuple value to contain `version` and `hashbytes` buffers'
);
}
return {
version: versionCV.buffer,
hashBytes: hashBytesCV.buffer,
};
}

export type PoxAddressArgs =
| [version: Buffer, hashBytes: Buffer, network: 'mainnet' | 'testnet']
| [poxAddrClarityValue: ClarityValue, network: 'mainnet' | 'testnet'];

export function poxAddressToBtcAddress(...args: PoxAddressArgs): string {
let version: Buffer, hashBytes: Buffer, network: 'mainnet' | 'testnet';
if (args.length === 3) {
[version, hashBytes, network] = args;
} else if (args.length === 2) {
({ version, hashBytes } = extractPoxAddressFromClarityValue(args[0]));
network = args[1];
} else {
throw new Error('Invalid arguments');
}
if (version.byteLength !== 1) {
throw new Error(`Invalid byte length for version buffer: ${version.toString('hex')}`);
}
Expand Down
23 changes: 23 additions & 0 deletions packages/stacking/tests/stacking.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
trueCV,
responseErrorCV,
intCV,
TupleCV,
ClarityType,
} from '@stacks/transactions';
import { address as btcAddress } from 'bitcoinjs-lib';
import { decodeBtcAddress, getAddressHashMode, InvalidAddressError, poxAddressToBtcAddress } from '../src/utils';
Expand Down Expand Up @@ -941,4 +943,25 @@ test('pox address to btc address', () => {
expect(decodedAddress.hashMode).toBe(item.version[0]);
expect(decodedAddress.data.toString('hex')).toBe(item.hashBytes.toString('hex'));
});

vectors.forEach(item => {
const clarityValue: TupleCV = {
type: ClarityType.Tuple,
data: {
version: {
type: ClarityType.Buffer,
buffer: item.version,
},
hashbytes: {
type: ClarityType.Buffer,
buffer: item.hashBytes,
},
},
};
const btcAddress = poxAddressToBtcAddress(clarityValue, item.network);
expect(btcAddress).toBe(item.expectedBtcAddr);
const decodedAddress = decodeBtcAddress(btcAddress);
expect(decodedAddress.hashMode).toBe(item.version[0]);
expect(decodedAddress.data.toString('hex')).toBe(item.hashBytes.toString('hex'));
});
});

1 comment on commit cb06f12

@vercel
Copy link

@vercel vercel bot commented on cb06f12 May 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.